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