xref: /csrg-svn/sys/kern/kern_exit.c (revision 52480)
1 /*
2  * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)kern_exit.c	7.40 (Berkeley) 02/13/92
8  */
9 
10 #include "param.h"
11 #include "systm.h"
12 #include "map.h"
13 #include "ioctl.h"
14 #include "tty.h"
15 #include "time.h"
16 #include "resource.h"
17 #include "kernel.h"
18 #include "proc.h"
19 #include "buf.h"
20 #include "wait.h"
21 #include "file.h"
22 #include "vnode.h"
23 #include "syslog.h"
24 #include "malloc.h"
25 #include "resourcevar.h"
26 
27 #include "machine/cpu.h"
28 #ifdef COMPAT_43
29 #include "machine/reg.h"
30 #include "machine/psl.h"
31 #endif
32 
33 #include "vm/vm.h"
34 #include "vm/vm_kern.h"
35 
36 /*
37  * Exit system call: pass back caller's arg
38  */
39 /* ARGSUSED */
40 rexit(p, uap, retval)
41 	struct proc *p;
42 	struct args {
43 		int	rval;
44 	} *uap;
45 	int *retval;
46 {
47 
48 	exit(p, W_EXITCODE(uap->rval, 0));
49 	/* NOTREACHED */
50 }
51 
52 /*
53  * Exit: deallocate address space and other resources,
54  * change proc state to zombie, and unlink proc from allproc
55  * and parent's lists.  Save exit status and rusage for wait().
56  * Check for child processes and orphan them.
57  */
58 exit(p, rv)
59 	register struct proc *p;
60 	int rv;
61 {
62 	register struct proc *q, *nq;
63 	register struct proc **pp;
64 	int s;
65 
66 #ifdef PGINPROF
67 	vmsizmon();
68 #endif
69 	MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage),
70 		M_ZOMBIE, M_WAITOK);
71 	/*
72 	 * If parent is waiting for us to exit or exec,
73 	 * SPPWAIT is set; we will wakeup the parent below.
74 	 */
75 	p->p_flag &= ~(STRC|SPPWAIT);
76 	p->p_flag |= SWEXIT;
77 	p->p_sigignore = ~0;
78 	p->p_sig = 0;
79 	untimeout(realitexpire, (caddr_t)p);
80 
81 	/*
82 	 * Close open files and release open-file table.
83 	 * This may block!
84 	 */
85 	fdfree(p);
86 
87 	/* The next two chunks should probably be moved to vmspace_exit. */
88 #ifdef SYSVSHM
89 	if (p->p_vmspace->vm_shm)
90 		shmexit(p);
91 #endif
92 	/*
93 	 * Release user portion of address space.
94 	 * This releases references to vnodes,
95 	 * which could cause I/O if the file has been unlinked.
96 	 * Need to do this early enough that we can still sleep.
97 	 * Can't free the entire vmspace as the kernel stack
98 	 * may be mapped within that space also.
99 	 */
100 	if (p->p_vmspace->vm_refcnt == 1)
101 		(void) vm_map_remove(&p->p_vmspace->vm_map, VM_MIN_ADDRESS,
102 		    VM_MAXUSER_ADDRESS);
103 
104 	if (p->p_pid == 1)
105 		panic("init died");
106 	if (SESS_LEADER(p)) {
107 		register struct session *sp = p->p_session;
108 
109 		if (sp->s_ttyvp) {
110 			/*
111 			 * Controlling process.
112 			 * Signal foreground pgrp,
113 			 * drain controlling terminal
114 			 * and revoke access to controlling terminal.
115 			 */
116 			if (sp->s_ttyp->t_session == sp) {
117 				if (sp->s_ttyp->t_pgrp)
118 					pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
119 				(void) ttywait(sp->s_ttyp);
120 				vgoneall(sp->s_ttyvp);
121 			}
122 			vrele(sp->s_ttyvp);
123 			sp->s_ttyvp = NULL;
124 			/*
125 			 * s_ttyp is not zero'd; we use this to indicate
126 			 * that the session once had a controlling terminal.
127 			 * (for logging and informational purposes)
128 			 */
129 		}
130 		sp->s_leader = NULL;
131 	}
132 	fixjobc(p, p->p_pgrp, 0);
133 	p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
134 	(void) acct(p);
135 #ifdef KTRACE
136 	/*
137 	 * release trace file
138 	 */
139 	p->p_traceflag = 0;	/* don't trace the vrele() */
140 	if (p->p_tracep)
141 		vrele(p->p_tracep);
142 #endif
143 	/*
144 	 * Clear curproc after we've done all operations
145 	 * that could block, and before tearing down
146 	 * the rest of the process state.
147 	 */
148 	curproc = NULL;
149 	if (--p->p_limit->p_refcnt == 0)
150 		FREE(p->p_limit, M_SUBPROC);
151 
152 	/*
153 	 * Remove proc from allproc queue and pidhash chain.
154 	 * Place onto zombproc.  Unlink from parent's child list.
155 	 */
156 	if (*p->p_prev = p->p_nxt)
157 		p->p_nxt->p_prev = p->p_prev;
158 	if (p->p_nxt = zombproc)
159 		p->p_nxt->p_prev = &p->p_nxt;
160 	p->p_prev = &zombproc;
161 	zombproc = p;
162 	p->p_stat = SZOMB;
163 	for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash)
164 		if (*pp == p) {
165 			*pp = p->p_hash;
166 			goto done;
167 		}
168 	panic("exit");
169 done:
170 
171 	if (p->p_cptr)		/* only need this if any child is S_ZOMB */
172 		wakeup((caddr_t) initproc);
173 	for (q = p->p_cptr; q != NULL; q = nq) {
174 		nq = q->p_osptr;
175 		if (nq != NULL)
176 			nq->p_ysptr = NULL;
177 		if (initproc->p_cptr)
178 			initproc->p_cptr->p_ysptr = q;
179 		q->p_osptr = initproc->p_cptr;
180 		q->p_ysptr = NULL;
181 		initproc->p_cptr = q;
182 
183 		q->p_pptr = initproc;
184 		/*
185 		 * Traced processes are killed
186 		 * since their existence means someone is screwing up.
187 		 */
188 		if (q->p_flag&STRC) {
189 			q->p_flag &= ~STRC;
190 			psignal(q, SIGKILL);
191 		}
192 	}
193 	p->p_cptr = NULL;
194 
195 	/*
196 	 * Save exit status and final rusage info,
197 	 * adding in child rusage info and self times.
198 	 */
199 	p->p_xstat = rv;
200 	*p->p_ru = p->p_stats->p_ru;
201 	p->p_ru->ru_stime = p->p_stime;
202 	p->p_ru->ru_utime = p->p_utime;
203 	ruadd(p->p_ru, &p->p_stats->p_cru);
204 
205 	/*
206 	 * Notify parent that we're gone.
207 	 */
208 	psignal(p->p_pptr, SIGCHLD);
209 	wakeup((caddr_t)p->p_pptr);
210 #if defined(tahoe)
211 	/* move this to cpu_exit */
212 	p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL;
213 #endif
214 	/*
215 	 * Finally, call machine-dependent code to release the remaining
216 	 * resources including address space, the kernel stack and pcb.
217 	 * The address space is released by "vmspace_free(p->p_vmspace)";
218 	 * This is machine-dependent, as we may have to change stacks
219 	 * or ensure that the current one isn't reallocated before we
220 	 * finish.  cpu_exit will end with a call to swtch(), finishing
221 	 * our execution (pun intended).
222 	 */
223 	cpu_exit(p);
224 	/* NOTREACHED */
225 }
226 
227 #ifdef COMPAT_43
228 owait(p, uap, retval)
229 	struct proc *p;
230 	register struct args {
231 		int	pid;
232 		int	*status;
233 		int	options;
234 		struct	rusage *rusage;
235 		int	compat;
236 	} *uap;
237 	int *retval;
238 {
239 
240 #ifdef PSL_ALLCC
241 	if ((p->p_md.md_regs[PS] & PSL_ALLCC) != PSL_ALLCC) {
242 		uap->options = 0;
243 		uap->rusage = 0;
244 	} else {
245 		uap->options = p->p_md.md_regs[R0];
246 		uap->rusage = (struct rusage *)p->p_md.md_regs[R1];
247 	}
248 #else
249 	uap->options = 0;
250 	uap->rusage = 0;
251 #endif
252 	uap->pid = WAIT_ANY;
253 	uap->status = 0;
254 	uap->compat = 1;
255 	return (wait1(p, uap, retval));
256 }
257 
258 wait4(p, uap, retval)
259 	struct proc *p;
260 	struct args {
261 		int	pid;
262 		int	*status;
263 		int	options;
264 		struct	rusage *rusage;
265 		int	compat;
266 	} *uap;
267 	int *retval;
268 {
269 
270 	uap->compat = 0;
271 	return (wait1(p, uap, retval));
272 }
273 #else
274 #define	wait1	wait4
275 #endif
276 
277 /*
278  * Wait: check child processes to see if any have exited,
279  * stopped under trace, or (optionally) stopped by a signal.
280  * Pass back status and deallocate exited child's proc structure.
281  */
282 wait1(q, uap, retval)
283 	register struct proc *q;
284 	register struct args {
285 		int	pid;
286 		int	*status;
287 		int	options;
288 		struct	rusage *rusage;
289 #ifdef COMPAT_43
290 		int compat;
291 #endif
292 	} *uap;
293 	int retval[];
294 {
295 	register int nfound;
296 	register struct proc *p;
297 	int status, error;
298 
299 	if (uap->pid == 0)
300 		uap->pid = -q->p_pgid;
301 #ifdef notyet
302 	if (uap->options &~ (WUNTRACED|WNOHANG))
303 		return (EINVAL);
304 #endif
305 loop:
306 	nfound = 0;
307 	for (p = q->p_cptr; p; p = p->p_osptr) {
308 		if (uap->pid != WAIT_ANY &&
309 		    p->p_pid != uap->pid && p->p_pgid != -uap->pid)
310 			continue;
311 		nfound++;
312 		if (p->p_stat == SZOMB) {
313 			retval[0] = p->p_pid;
314 #ifdef COMPAT_43
315 			if (uap->compat)
316 				retval[1] = p->p_xstat;
317 			else
318 #endif
319 			if (uap->status) {
320 				status = p->p_xstat;	/* convert to int */
321 				if (error = copyout((caddr_t)&status,
322 				    (caddr_t)uap->status, sizeof(status)))
323 					return (error);
324 			}
325 			if (uap->rusage && (error = copyout((caddr_t)p->p_ru,
326 			    (caddr_t)uap->rusage, sizeof (struct rusage))))
327 				return (error);
328 			p->p_xstat = 0;
329 			ruadd(&q->p_stats->p_cru, p->p_ru);
330 			FREE(p->p_ru, M_ZOMBIE);
331 			if (--p->p_cred->p_refcnt == 0) {
332 				crfree(p->p_cred->pc_ucred);
333 				FREE(p->p_cred, M_SUBPROC);
334 			}
335 
336 			/*
337 			 * Finally finished with old proc entry.
338 			 * Unlink it from its process group and free it.
339 			 */
340 			leavepgrp(p);
341 			if (*p->p_prev = p->p_nxt)	/* off zombproc */
342 				p->p_nxt->p_prev = p->p_prev;
343 			if (q = p->p_ysptr)
344 				q->p_osptr = p->p_osptr;
345 			if (q = p->p_osptr)
346 				q->p_ysptr = p->p_ysptr;
347 			if ((q = p->p_pptr)->p_cptr == p)
348 				q->p_cptr = p->p_osptr;
349 
350 			/*
351 			 * Give machine-dependent layer a chance
352 			 * to free anything that cpu_exit couldn't
353 			 * release while still running in process context.
354 			 */
355 			cpu_wait(p);
356 			FREE(p, M_PROC);
357 			nprocs--;
358 			return (0);
359 		}
360 		if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 &&
361 		    (p->p_flag & STRC || uap->options & WUNTRACED)) {
362 			p->p_flag |= SWTED;
363 			retval[0] = p->p_pid;
364 #ifdef COMPAT_43
365 			if (uap->compat) {
366 				retval[1] = W_STOPCODE(p->p_xstat);
367 				error = 0;
368 			} else
369 #endif
370 			if (uap->status) {
371 				status = W_STOPCODE(p->p_xstat);
372 				error = copyout((caddr_t)&status,
373 					(caddr_t)uap->status, sizeof(status));
374 			} else
375 				error = 0;
376 			return (error);
377 		}
378 	}
379 	if (nfound == 0)
380 		return (ECHILD);
381 	if (uap->options & WNOHANG) {
382 		retval[0] = 0;
383 		return (0);
384 	}
385 	if (error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0))
386 		return (error);
387 	goto loop;
388 }
389