xref: /original-bsd/sys/kern/kern_exit.c (revision 5a948429)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  *	@(#)kern_exit.c	7.8 (Berkeley) 09/03/89
18  */
19 
20 #include "param.h"
21 #include "systm.h"
22 #include "map.h"
23 #include "user.h"
24 #include "kernel.h"
25 #include "proc.h"
26 #include "buf.h"
27 #include "wait.h"
28 #include "vm.h"
29 #include "file.h"
30 #include "vnode.h"
31 #include "tty.h"
32 #include "syslog.h"
33 #include "malloc.h"
34 
35 #include "machine/reg.h"
36 #ifdef COMPAT_43
37 #include "machine/psl.h"
38 #endif
39 
40 /*
41  * Exit system call: pass back caller's arg
42  */
43 rexit()
44 {
45 	register struct a {
46 		int	rval;
47 	} *uap;
48 	union wait status;
49 
50 	uap = (struct a *)u.u_ap;
51 	status.w_status = 0;
52 	status.w_retcode = uap->rval;
53 	exit(status.w_status);
54 }
55 
56 /*
57  * Release resources.
58  * Save u. area for parent to look at.
59  * Enter zombie state.
60  * Wake up parent and init processes,
61  * and dispose of children.
62  */
63 exit(rv)
64 	int rv;
65 {
66 	register int i;
67 	register struct proc *p, *q, *nq;
68 	register int x;
69 
70 #ifdef PGINPROF
71 	vmsizmon();
72 #endif
73 	p = u.u_procp;
74 	MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage),
75 		M_ZOMBIE, M_WAITOK);
76 	p->p_flag &= ~(STRC|SULOCK);
77 	p->p_flag |= SWEXIT;
78 	p->p_sigignore = ~0;
79 	p->p_cpticks = 0;
80 	p->p_pctcpu = 0;
81 	for (i = 0; i < NSIG; i++)
82 		u.u_signal[i] = SIG_IGN;
83 	untimeout(realitexpire, (caddr_t)p);
84 	/*
85 	 * Release virtual memory.  If we resulted from
86 	 * a vfork(), instead give the resources back to
87 	 * the parent.
88 	 */
89 	if ((p->p_flag & SVFORK) == 0)
90 		vrelvm();
91 	else {
92 		p->p_flag &= ~SVFORK;
93 		wakeup((caddr_t)p);
94 		while ((p->p_flag & SVFDONE) == 0)
95 			sleep((caddr_t)p, PZERO - 1);
96 		p->p_flag &= ~SVFDONE;
97 	}
98 	for (i = 0; i <= u.u_lastfile; i++) {
99 		struct file *f;
100 
101 		f = u.u_ofile[i];
102 		if (f) {
103 			u.u_ofile[i] = NULL;
104 			u.u_pofile[i] = 0;
105 			closef(f);
106 		}
107 	}
108 	if (SESS_LEADER(p)) {
109 		p->p_session->s_leader = 0;
110 		/* TODO: vhangup(); */
111 		if (u.u_ttyp) {
112 			u.u_ttyp->t_session = 0;
113 			u.u_ttyp->t_pgid = 0;
114 		}
115 	}
116 	VOP_LOCK(u.u_cdir);
117 	vput(u.u_cdir);
118 	if (u.u_rdir) {
119 		VOP_LOCK(u.u_rdir);
120 		vput(u.u_rdir);
121 	}
122 	u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
123 	acct();
124 #ifdef QUOTA
125 	qclean();
126 #endif
127 	crfree(u.u_cred);
128 #ifdef KTRACE
129 	/*
130 	 * release trace file
131 	 */
132 	if (p->p_tracep)
133 		vrele(p->p_tracep);
134 #endif
135 	/*
136 	/*
137 	 * Freeing the user structure and kernel stack
138 	 * for the current process: have to run a bit longer
139 	 * using the pages which are about to be freed...
140 	 * vrelu will block memory allocation by raising ipl.
141 	 */
142 	vrelu(u.u_procp, 0);
143 	vrelpt(u.u_procp);
144 	if (*p->p_prev = p->p_nxt)		/* off allproc queue */
145 		p->p_nxt->p_prev = p->p_prev;
146 	if (p->p_nxt = zombproc)		/* onto zombproc */
147 		p->p_nxt->p_prev = &p->p_nxt;
148 	p->p_prev = &zombproc;
149 	zombproc = p;
150 	multprog--;
151 	p->p_stat = SZOMB;
152 	noproc = 1;
153 	i = PIDHASH(p->p_pid);
154 	x = p - proc;
155 	if (pidhash[i] == x)
156 		pidhash[i] = p->p_idhash;
157 	else {
158 		for (i = pidhash[i]; i != 0; i = proc[i].p_idhash)
159 			if (proc[i].p_idhash == x) {
160 				proc[i].p_idhash = p->p_idhash;
161 				goto done;
162 			}
163 		panic("exit");
164 	}
165 	if (p->p_pid == 1) {
166 		if (p->p_dsize == 0) {
167 			printf("Can't exec init (errno %d)\n", rv >> 8);
168 			for (;;)
169 				;
170 		} else
171 			panic("init died");
172 	}
173 done:
174 	p->p_xstat = rv;
175 	*p->p_ru = u.u_ru;
176 	ruadd(p->p_ru, &u.u_cru);
177 	if (p->p_cptr)		/* only need this if any child is S_ZOMB */
178 		wakeup((caddr_t)&proc[1]);
179 	if (PGRP_JOBC(p))
180 		p->p_pgrp->pg_jobc--;
181 	for (q = p->p_cptr; q != NULL; q = nq) {
182 		if (PGRP_JOBC(q))
183 			q->p_pgrp->pg_jobc--;
184 		nq = q->p_osptr;
185 		if (nq != NULL)
186 			nq->p_ysptr = NULL;
187 		if (proc[1].p_cptr)
188 			proc[1].p_cptr->p_ysptr = q;
189 		q->p_osptr = proc[1].p_cptr;
190 		q->p_ysptr = NULL;
191 		proc[1].p_cptr = q;
192 
193 		q->p_pptr = &proc[1];
194 		q->p_ppid = 1;
195 		/*
196 		 * Traced processes are killed
197 		 * since their existence means someone is screwing up.
198 		 * Stopped processes are sent a hangup and a continue.
199 		 * This is designed to be ``safe'' for setuid
200 		 * processes since they must be willing to tolerate
201 		 * hangups anyways.
202 		 */
203 		if (q->p_flag&STRC) {
204 			q->p_flag &= ~STRC;
205 			psignal(q, SIGKILL);
206 		} else if (q->p_stat == SSTOP) {
207 			psignal(q, SIGHUP);
208 			psignal(q, SIGCONT);
209 		}
210 		/*
211 		 * Protect this process from future
212 		 * tty signals, clear TSTP/TTIN/TTOU if pending.
213 		 */
214 		(void) spgrp(q);
215 	}
216 	p->p_cptr = NULL;
217 	psignal(p->p_pptr, SIGCHLD);
218 	wakeup((caddr_t)p->p_pptr);
219 #if defined(tahoe)
220 	dkeyrelease(p->p_dkey), p->p_dkey = 0;
221 	ckeyrelease(p->p_ckey), p->p_ckey = 0;
222 	u.u_pcb.pcb_savacc.faddr = (float *)NULL;
223 #endif
224 	swtch();
225 }
226 
227 #ifdef COMPAT_43
228 owait()
229 {
230 	struct a {
231 		int	pid;
232 		union	wait *status;
233 		int	options;
234 		struct	rusage *rusage;
235 	} *uap = (struct a *)u.u_ap;
236 
237 	if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) {
238 		uap->options = 0;
239 		uap->rusage = 0;
240 	} else {
241 		uap->options = u.u_ar0[R0];
242 		uap->rusage = (struct rusage *)u.u_ar0[R1];
243 	}
244 	uap->pid = WAIT_ANY;
245 	uap->status = 0;
246 	wait1(1);
247 }
248 
249 wait4()
250 {
251 	wait1(0);
252 }
253 #endif
254 
255 /*
256  * Wait system call.
257  * Search for a terminated (zombie) child,
258  * finally lay it to rest, and collect its status.
259  * Look also for stopped (traced) children,
260  * and pass back status from them.
261  */
262 #ifdef COMPAT_43
263 wait1(compat)
264 	int compat;
265 #else
266 wait4()
267 #endif
268 {
269 	register struct a {
270 		int	pid;
271 		union	wait *status;
272 		int	options;
273 		struct	rusage *rusage;
274 	} *uap = (struct a *)u.u_ap;
275 	register f;
276 	register struct proc *p, *q;
277 	union wait status;
278 
279 	q = u.u_procp;
280 	if (uap->pid == 0)
281 		uap->pid = -q->p_pgid;
282 #ifdef notyet
283 	if (uap->options &~ (WUNTRACED|WNOHANG)) {
284 		u.u_error = EINVAL;
285 		return;
286 	}
287 #endif
288 loop:
289 	f = 0;
290 	for (p = q->p_cptr; p; p = p->p_osptr) {
291 		if (uap->pid != WAIT_ANY &&
292 		    p->p_pid != uap->pid && p->p_pgid != -uap->pid)
293 			continue;
294 		f++;
295 		if (p->p_stat == SZOMB) {
296 			pgrm(p);			/* off pgrp */
297 			u.u_r.r_val1 = p->p_pid;
298 #ifdef COMPAT_43
299 			if (compat)
300 				u.u_r.r_val2 = p->p_xstat;
301 			else
302 #endif
303 			if (uap->status) {
304 				status.w_status = p->p_xstat;
305 				if (u.u_error = copyout((caddr_t)&status,
306 				    (caddr_t)uap->status, sizeof(status)))
307 					return;
308 			}
309 			p->p_xstat = 0;
310 			if (uap->rusage)
311 				u.u_error = copyout((caddr_t)p->p_ru,
312 				    (caddr_t)uap->rusage,
313 				    sizeof (struct rusage));
314 			ruadd(&u.u_cru, p->p_ru);
315 			FREE(p->p_ru, M_ZOMBIE);
316 			p->p_ru = 0;
317 			p->p_stat = NULL;
318 			p->p_pid = 0;
319 			p->p_ppid = 0;
320 			if (*p->p_prev = p->p_nxt)	/* off zombproc */
321 				p->p_nxt->p_prev = p->p_prev;
322 			p->p_nxt = freeproc;		/* onto freeproc */
323 			freeproc = p;
324 			if (q = p->p_ysptr)
325 				q->p_osptr = p->p_osptr;
326 			if (q = p->p_osptr)
327 				q->p_ysptr = p->p_ysptr;
328 			if ((q = p->p_pptr)->p_cptr == p)
329 				q->p_cptr = p->p_osptr;
330 			p->p_pptr = 0;
331 			p->p_ysptr = 0;
332 			p->p_osptr = 0;
333 			p->p_cptr = 0;
334 			p->p_sig = 0;
335 			p->p_sigcatch = 0;
336 			p->p_sigignore = 0;
337 			p->p_sigmask = 0;
338 			/*p->p_pgrp = 0;*/
339 			p->p_flag = 0;
340 			p->p_wchan = 0;
341 			p->p_cursig = 0;
342 			return;
343 		}
344 		if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 &&
345 		    (p->p_flag & STRC || uap->options & WUNTRACED)) {
346 			p->p_flag |= SWTED;
347 			u.u_r.r_val1 = p->p_pid;
348 #ifdef COMPAT_43
349 			if (compat)
350 				u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED;
351 			else
352 #endif
353 			if (uap->status) {
354 				status.w_status = 0;
355 				status.w_stopval = WSTOPPED;
356 				status.w_stopsig = p->p_cursig;
357 				u.u_error = copyout((caddr_t)&status,
358 				    (caddr_t)uap->status, sizeof(status));
359 			}
360 			return;
361 		}
362 	}
363 	if (f == 0) {
364 		u.u_error = ECHILD;
365 		return;
366 	}
367 	if (uap->options & WNOHANG) {
368 		u.u_r.r_val1 = 0;
369 		return;
370 	}
371 	if (setjmp(&u.u_qsave)) {
372 		p = u.u_procp;
373 		if ((u.u_sigintr & sigmask(p->p_cursig)) != 0) {
374 			u.u_error = EINTR;
375 			return;
376 		}
377 		u.u_eosys = RESTARTSYS;
378 		return;
379 	}
380 	sleep((caddr_t)u.u_procp, PWAIT);
381 	goto loop;
382 }
383