xref: /csrg-svn/sys/kern/kern_exit.c (revision 44404)
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.25 (Berkeley) 06/28/90
18  */
19 
20 #include "param.h"
21 #include "systm.h"
22 #include "map.h"
23 #include "ioctl.h"
24 #include "tty.h"
25 #include "user.h"
26 #include "kernel.h"
27 #include "proc.h"
28 #include "buf.h"
29 #include "wait.h"
30 #include "vm.h"
31 #include "file.h"
32 #include "vnode.h"
33 #include "syslog.h"
34 #include "malloc.h"
35 
36 #include "machine/reg.h"
37 #ifdef COMPAT_43
38 #include "machine/psl.h"
39 #endif
40 
41 /*
42  * Exit system call: pass back caller's arg
43  */
44 /* ARGSUSED */
45 rexit(p, uap, retval)
46 	struct proc *p;
47 	struct args {
48 		int	rval;
49 	} *uap;
50 	int *retval;
51 {
52 
53 	return (exit(p, W_EXITCODE(uap->rval, 0)));
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(p, rv)
64 	struct proc *p;
65 	int rv;
66 {
67 	register int i;
68 	register struct proc *q, *nq;
69 	register struct proc **pp;
70 
71 #ifdef PGINPROF
72 	vmsizmon();
73 #endif
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_sig = 0;
80 	p->p_cpticks = 0;
81 	p->p_pctcpu = 0;
82 	for (i = 0; i < NSIG; i++)
83 		u.u_signal[i] = SIG_IGN;
84 	untimeout(realitexpire, (caddr_t)p);
85 	/*
86 	 * Release virtual memory.  If we resulted from
87 	 * a vfork(), instead give the resources back to
88 	 * the parent.
89 	 */
90 	if ((p->p_flag & SVFORK) == 0) {
91 #ifdef MAPMEM
92 		if (u.u_mmap)
93 			(void) mmexit(p);
94 #endif
95 		vrelvm();
96 	} else {
97 		p->p_flag &= ~SVFORK;
98 		wakeup((caddr_t)p);
99 		while ((p->p_flag & SVFDONE) == 0)
100 			sleep((caddr_t)p, PZERO - 1);
101 		p->p_flag &= ~SVFDONE;
102 	}
103 	for (i = 0; i <= u.u_lastfile; i++) {
104 		struct file *f;
105 
106 		f = u.u_ofile[i];
107 		if (f) {
108 			u.u_ofile[i] = NULL;
109 			u.u_pofile[i] = 0;
110 			(void) closef(f);
111 		}
112 	}
113 	if (SESS_LEADER(p)) {
114 		register struct session *sp = p->p_session;
115 
116 		if (sp->s_ttyvp) {
117 			/*
118 			 * Controlling process.
119 			 * Signal foreground pgrp and revoke access
120 			 * to controlling terminal.
121 			 */
122 			if (sp->s_ttyp->t_pgrp)
123 				pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
124 			vgoneall(sp->s_ttyvp);
125 			vrele(sp->s_ttyvp);
126 			sp->s_ttyvp = NULL;
127 			/*
128 			 * s_ttyp is not zero'd; we use this to indicate
129 			 * that the session once had a controlling terminal.
130 			 * (for logging and informational purposes)
131 			 */
132 		}
133 		sp->s_leader = 0;
134 	}
135 	VOP_LOCK(u.u_cdir);
136 	vput(u.u_cdir);
137 	if (u.u_rdir) {
138 		VOP_LOCK(u.u_rdir);
139 		vput(u.u_rdir);
140 	}
141 	u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
142 	(void) acct(p);
143 	crfree(u.u_cred);
144 #ifdef KTRACE
145 	/*
146 	 * release trace file
147 	 */
148 	if (p->p_tracep)
149 		vrele(p->p_tracep);
150 #endif
151 	/*
152 	 * Freeing the user structure and kernel stack
153 	 * for the current process: have to run a bit longer
154 	 * using the pages which are about to be freed...
155 	 * vrelu will block memory allocation by raising ipl.
156 	 */
157 	vrelu(p, 0);
158 	vrelpt(p);
159 	if (*p->p_prev = p->p_nxt)		/* off allproc queue */
160 		p->p_nxt->p_prev = p->p_prev;
161 	if (p->p_nxt = zombproc)		/* onto zombproc */
162 		p->p_nxt->p_prev = &p->p_nxt;
163 	p->p_prev = &zombproc;
164 	zombproc = p;
165 	multprog--;
166 	p->p_stat = SZOMB;
167 	noproc = 1;
168 	for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash)
169 		if (*pp == p) {
170 			*pp = p->p_hash;
171 			goto done;
172 		}
173 	panic("exit");
174 done:
175 	if (p->p_pid == 1) {
176 		if (p->p_dsize == 0) {
177 			printf("Can't exec init (errno %d)\n", WEXITSTATUS(rv));
178 			for (;;)
179 				;
180 		} else
181 			panic("init died");
182 	}
183 	p->p_xstat = rv;
184 	*p->p_ru = u.u_ru;
185 	i = splclock();
186 	p->p_ru->ru_stime = p->p_stime;
187 	p->p_ru->ru_utime = p->p_utime;
188 	splx(i);
189 	ruadd(p->p_ru, &u.u_cru);
190 	if (p->p_cptr)		/* only need this if any child is S_ZOMB */
191 		wakeup((caddr_t)&proc[1]);
192 	fixjobc(p, 0);
193 	for (q = p->p_cptr; q != NULL; q = nq) {
194 		nq = q->p_osptr;
195 		if (nq != NULL)
196 			nq->p_ysptr = NULL;
197 		if (proc[1].p_cptr)
198 			proc[1].p_cptr->p_ysptr = q;
199 		q->p_osptr = proc[1].p_cptr;
200 		q->p_ysptr = NULL;
201 		proc[1].p_cptr = q;
202 
203 		q->p_pptr = &proc[1];
204 		q->p_ppid = 1;
205 		/*
206 		 * Traced processes are killed
207 		 * since their existence means someone is screwing up.
208 		 */
209 		if (q->p_flag&STRC) {
210 			q->p_flag &= ~STRC;
211 			psignal(q, SIGKILL);
212 		}
213 	}
214 	p->p_cptr = NULL;
215 	psignal(p->p_pptr, SIGCHLD);
216 	wakeup((caddr_t)p->p_pptr);
217 #if defined(tahoe)
218 	dkeyrelease(p->p_dkey), p->p_dkey = 0;
219 	ckeyrelease(p->p_ckey), p->p_ckey = 0;
220 	u.u_pcb.pcb_savacc.faddr = (float *)NULL;
221 #endif
222 	swtch();
223 }
224 
225 #ifdef COMPAT_43
226 owait(p, uap, retval)
227 	struct proc *p;
228 	register struct args {
229 		int	pid;
230 		int	*status;
231 		int	options;
232 		struct	rusage *rusage;
233 		int	compat;
234 	} *uap;
235 	int *retval;
236 {
237 
238 	if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) {
239 		uap->options = 0;
240 		uap->rusage = 0;
241 	} else {
242 		uap->options = u.u_ar0[R0];
243 		uap->rusage = (struct rusage *)u.u_ar0[R1];
244 	}
245 	uap->pid = WAIT_ANY;
246 	uap->status = 0;
247 	uap->compat = 1;
248 	return (wait1(p, uap, retval));
249 }
250 
251 wait4(p, uap, retval)
252 	struct proc *p;
253 	struct args {
254 		int	pid;
255 		int	*status;
256 		int	options;
257 		struct	rusage *rusage;
258 		int	compat;
259 	} *uap;
260 	int *retval;
261 {
262 
263 	uap->compat = 0;
264 	return (wait1(p, uap, retval));
265 }
266 #else
267 #define	wait1	wait4
268 #endif
269 
270 /*
271  * Wait system call.
272  * Search for a terminated (zombie) child,
273  * finally lay it to rest, and collect its status.
274  * Look also for stopped (traced) children,
275  * and pass back status from them.
276  */
277 wait1(q, uap, retval)
278 	register struct proc *q;
279 	register struct args {
280 		int	pid;
281 		int	*status;
282 		int	options;
283 		struct	rusage *rusage;
284 #ifdef COMPAT_43
285 		int compat;
286 #endif
287 	} *uap;
288 	int retval[];
289 {
290 	register int f;
291 	register struct proc *p;
292 	int status, error;
293 
294 	if (uap->pid == 0)
295 		uap->pid = -q->p_pgid;
296 #ifdef notyet
297 	if (uap->options &~ (WUNTRACED|WNOHANG))
298 		return (EINVAL);
299 #endif
300 loop:
301 	f = 0;
302 	for (p = q->p_cptr; p; p = p->p_osptr) {
303 		if (uap->pid != WAIT_ANY &&
304 		    p->p_pid != uap->pid && p->p_pgid != -uap->pid)
305 			continue;
306 		f++;
307 		if (p->p_stat == SZOMB) {
308 			retval[0] = p->p_pid;
309 #ifdef COMPAT_43
310 			if (uap->compat)
311 				retval[1] = p->p_xstat;
312 			else
313 #endif
314 			if (uap->status) {
315 				status = p->p_xstat;	/* convert to int */
316 				if (error = copyout((caddr_t)&status,
317 				    (caddr_t)uap->status, sizeof(status)))
318 					return (error);
319 			}
320 			if (uap->rusage && (error = copyout((caddr_t)p->p_ru,
321 			    (caddr_t)uap->rusage, sizeof (struct rusage))))
322 				return (error);
323 			pgrm(p);			/* off pgrp */
324 			p->p_xstat = 0;
325 			ruadd(&u.u_cru, p->p_ru);
326 			FREE(p->p_ru, M_ZOMBIE);
327 			p->p_ru = 0;
328 			p->p_stat = NULL;
329 			p->p_pid = 0;
330 			p->p_ppid = 0;
331 			if (*p->p_prev = p->p_nxt)	/* off zombproc */
332 				p->p_nxt->p_prev = p->p_prev;
333 			p->p_nxt = freeproc;		/* onto freeproc */
334 			freeproc = p;
335 			if (q = p->p_ysptr)
336 				q->p_osptr = p->p_osptr;
337 			if (q = p->p_osptr)
338 				q->p_ysptr = p->p_ysptr;
339 			if ((q = p->p_pptr)->p_cptr == p)
340 				q->p_cptr = p->p_osptr;
341 			p->p_pptr = 0;
342 			p->p_ysptr = 0;
343 			p->p_osptr = 0;
344 			p->p_cptr = 0;
345 			p->p_sig = 0;
346 			p->p_sigcatch = 0;
347 			p->p_sigignore = 0;
348 			p->p_sigmask = 0;
349 			/*p->p_pgrp = 0;*/
350 			p->p_flag = 0;
351 			p->p_wchan = 0;
352 			return (0);
353 		}
354 		if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 &&
355 		    (p->p_flag & STRC || uap->options & WUNTRACED)) {
356 			p->p_flag |= SWTED;
357 			retval[0] = p->p_pid;
358 #ifdef COMPAT_43
359 			if (uap->compat) {
360 				retval[1] = W_STOPCODE(p->p_xstat);
361 				error = 0;
362 			} else
363 #endif
364 			if (uap->status) {
365 				status = W_STOPCODE(p->p_xstat);
366 				error = copyout((caddr_t)&status,
367 				    (caddr_t)uap->status, sizeof(status));
368 			} else
369 				error = 0;
370 			return (error);
371 		}
372 	}
373 	if (f == 0)
374 		return (ECHILD);
375 	if (uap->options & WNOHANG) {
376 		retval[0] = 0;
377 		return (0);
378 	}
379 	if (error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0))
380 		return (error);
381 	goto loop;
382 }
383