xref: /original-bsd/sys/kern/kern_exit.c (revision 5458d02b)
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.32 (Berkeley) 04/20/91
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 #ifdef COMPAT_43
28 #include "machine/reg.h"
29 #include "machine/psl.h"
30 #endif
31 
32 #include "vm/vm.h"
33 #include "vm/vm_kern.h"
34 
35 /*
36  * Exit system call: pass back caller's arg
37  */
38 /* ARGSUSED */
39 rexit(p, uap, retval)
40 	struct proc *p;
41 	struct args {
42 		int	rval;
43 	} *uap;
44 	int *retval;
45 {
46 
47 	exit(p, W_EXITCODE(uap->rval, 0));
48 	/* NOTREACHED */
49 }
50 
51 /*
52  * Exit: deallocate address space and other resources,
53  * change proc state to zombie, and unlink proc from allproc
54  * and parent's lists.  Save exit status and rusage for wait().
55  * Check for child processes and orphan them.
56  */
57 exit(p, rv)
58 	register struct proc *p;
59 	int rv;
60 {
61 	register struct proc *q, *nq;
62 	register struct proc **pp;
63 	int s;
64 
65 #ifdef PGINPROF
66 	vmsizmon();
67 #endif
68 	MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage),
69 		M_ZOMBIE, M_WAITOK);
70 	/*
71 	 * If parent is waiting for us to exit or exec,
72 	 * SPPWAIT is set; we will wakeup the parent below.
73 	 */
74 	p->p_flag &= ~(STRC|SPPWAIT);
75 	p->p_flag |= SWEXIT;
76 	p->p_sigignore = ~0;
77 	p->p_sig = 0;
78 	untimeout(realitexpire, (caddr_t)p);
79 
80 	/*
81 	 * Close open files and release open-file table.
82 	 * This may block!
83 	 */
84 	fdfree(p);
85 p->p_fd = 0;
86 #ifdef SYSVSHM
87 	if (p->p_vmspace->vm_shm)
88 		shmexit(p);
89 #endif
90 	vmspace_free(p->p_vmspace);
91 p->p_vmspace = 0;
92 
93 	if (p->p_pid == 1)
94 		panic("init died");
95 	if (SESS_LEADER(p)) {
96 		register struct session *sp = p->p_session;
97 
98 		if (sp->s_ttyvp) {
99 			/*
100 			 * Controlling process.
101 			 * Signal foreground pgrp and revoke access
102 			 * to controlling terminal.
103 			 */
104 			if (sp->s_ttyp->t_pgrp)
105 				pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
106 			vgoneall(sp->s_ttyvp);
107 			vrele(sp->s_ttyvp);
108 			sp->s_ttyvp = NULL;
109 			/*
110 			 * s_ttyp is not zero'd; we use this to indicate
111 			 * that the session once had a controlling terminal.
112 			 * (for logging and informational purposes)
113 			 */
114 		}
115 		sp->s_leader = 0;
116 	}
117 	fixjobc(p, p->p_pgrp, 0);
118 	p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
119 	(void) acct(p);
120 	if (--p->p_limit->p_refcnt == 0)
121 		FREE(p->p_limit, M_SUBPROC);
122 	if (--p->p_cred->p_refcnt == 0) {
123 		crfree(p->p_cred->pc_ucred);
124 		FREE(p->p_cred, M_SUBPROC);
125 	}
126 #ifdef KTRACE
127 	/*
128 	 * release trace file
129 	 */
130 	if (p->p_tracep)
131 		vrele(p->p_tracep);
132 #endif
133 
134 	/*
135 	 * Remove proc from allproc queue and pidhash chain.
136 	 * Place onto zombproc.  Unlink from parent's child list.
137 	 */
138 	if (*p->p_prev = p->p_nxt)
139 		p->p_nxt->p_prev = p->p_prev;
140 	if (p->p_nxt = zombproc)
141 		p->p_nxt->p_prev = &p->p_nxt;
142 	p->p_prev = &zombproc;
143 	zombproc = p;
144 	p->p_stat = SZOMB;
145 	curproc = NULL;
146 	for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash)
147 		if (*pp == p) {
148 			*pp = p->p_hash;
149 			goto done;
150 		}
151 	panic("exit");
152 done:
153 
154 	if (p->p_cptr)		/* only need this if any child is S_ZOMB */
155 		wakeup((caddr_t) initproc);
156 	for (q = p->p_cptr; q != NULL; q = nq) {
157 		nq = q->p_osptr;
158 		if (nq != NULL)
159 			nq->p_ysptr = NULL;
160 		if (initproc->p_cptr)
161 			initproc->p_cptr->p_ysptr = q;
162 		q->p_osptr = initproc->p_cptr;
163 		q->p_ysptr = NULL;
164 		initproc->p_cptr = q;
165 
166 		q->p_pptr = initproc;
167 		/*
168 		 * Traced processes are killed
169 		 * since their existence means someone is screwing up.
170 		 */
171 		if (q->p_flag&STRC) {
172 			q->p_flag &= ~STRC;
173 			psignal(q, SIGKILL);
174 		}
175 	}
176 	p->p_cptr = NULL;
177 
178 	/*
179 	 * Save exit status and final rusage info,
180 	 * adding in child rusage info and self times.
181 	 */
182 	p->p_xstat = rv;
183 	*p->p_ru = p->p_stats->p_ru;
184 	p->p_ru->ru_stime = p->p_stime;
185 	p->p_ru->ru_utime = p->p_utime;
186 	ruadd(p->p_ru, &p->p_stats->p_cru);
187 
188 	/*
189 	 * Notify parent that we're gone.
190 	 */
191 	psignal(p->p_pptr, SIGCHLD);
192 	wakeup((caddr_t)p->p_pptr);
193 #if defined(tahoe)
194 	u.u_pcb.pcb_savacc.faddr = (float *)NULL;
195 #endif
196 	/*
197 	 * Free the memory for the user structure and kernel stack.
198 	 * As we continue using it until the swtch completes
199 	 * (or switches to an interrupt stack), we need to block
200 	 * memory allocation by raising priority until we are gone.
201 	 */
202 	(void) splimp();
203 	/* I don't think this will cause a sleep/realloc anywhere... */
204 	kmem_free(kernel_map, (vm_offset_t)p->p_addr,
205 	    round_page(ctob(UPAGES)));
206 	swtch();
207 	/* NOTREACHED */
208 }
209 
210 #ifdef COMPAT_43
211 owait(p, uap, retval)
212 	struct proc *p;
213 	register struct args {
214 		int	pid;
215 		int	*status;
216 		int	options;
217 		struct	rusage *rusage;
218 		int	compat;
219 	} *uap;
220 	int *retval;
221 {
222 
223 	if ((p->p_regs[PS] & PSL_ALLCC) != PSL_ALLCC) {
224 		uap->options = 0;
225 		uap->rusage = 0;
226 	} else {
227 		uap->options = p->p_regs[R0];
228 		uap->rusage = (struct rusage *)p->p_regs[R1];
229 	}
230 	uap->pid = WAIT_ANY;
231 	uap->status = 0;
232 	uap->compat = 1;
233 	return (wait1(p, uap, retval));
234 }
235 
236 wait4(p, uap, retval)
237 	struct proc *p;
238 	struct args {
239 		int	pid;
240 		int	*status;
241 		int	options;
242 		struct	rusage *rusage;
243 		int	compat;
244 	} *uap;
245 	int *retval;
246 {
247 
248 	uap->compat = 0;
249 	return (wait1(p, uap, retval));
250 }
251 #else
252 #define	wait1	wait4
253 #endif
254 
255 /*
256  * Wait: check child processes to see if any have exited,
257  * stopped under trace, or (optionally) stopped by a signal.
258  * Pass back status and deallocate exited child's proc structure.
259  */
260 wait1(q, uap, retval)
261 	register struct proc *q;
262 	register struct args {
263 		int	pid;
264 		int	*status;
265 		int	options;
266 		struct	rusage *rusage;
267 #ifdef COMPAT_43
268 		int compat;
269 #endif
270 	} *uap;
271 	int retval[];
272 {
273 	register int nfound;
274 	register struct proc *p;
275 	int status, error;
276 
277 	if (uap->pid == 0)
278 		uap->pid = -q->p_pgid;
279 #ifdef notyet
280 	if (uap->options &~ (WUNTRACED|WNOHANG))
281 		return (EINVAL);
282 #endif
283 loop:
284 	nfound = 0;
285 	for (p = q->p_cptr; p; p = p->p_osptr) {
286 		if (uap->pid != WAIT_ANY &&
287 		    p->p_pid != uap->pid && p->p_pgid != -uap->pid)
288 			continue;
289 		nfound++;
290 		if (p->p_stat == SZOMB) {
291 			retval[0] = p->p_pid;
292 #ifdef COMPAT_43
293 			if (uap->compat)
294 				retval[1] = p->p_xstat;
295 			else
296 #endif
297 			if (uap->status) {
298 				status = p->p_xstat;	/* convert to int */
299 				if (error = copyout((caddr_t)&status,
300 				    (caddr_t)uap->status, sizeof(status)))
301 					return (error);
302 			}
303 			if (uap->rusage && (error = copyout((caddr_t)p->p_ru,
304 			    (caddr_t)uap->rusage, sizeof (struct rusage))))
305 				return (error);
306 			p->p_xstat = 0;
307 			ruadd(&q->p_stats->p_cru, p->p_ru);
308 			FREE(p->p_ru, M_ZOMBIE);
309 
310 			/*
311 			 * Finally finished with old proc entry.
312 			 * Unlink it from its process group and free it.
313 			 */
314 			leavepgrp(p);
315 			if (*p->p_prev = p->p_nxt)	/* off zombproc */
316 				p->p_nxt->p_prev = p->p_prev;
317 			if (q = p->p_ysptr)
318 				q->p_osptr = p->p_osptr;
319 			if (q = p->p_osptr)
320 				q->p_ysptr = p->p_ysptr;
321 			if ((q = p->p_pptr)->p_cptr == p)
322 				q->p_cptr = p->p_osptr;
323 			FREE(p, M_PROC);
324 			nprocs--;
325 			return (0);
326 		}
327 		if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 &&
328 		    (p->p_flag & STRC || uap->options & WUNTRACED)) {
329 			p->p_flag |= SWTED;
330 			retval[0] = p->p_pid;
331 #ifdef COMPAT_43
332 			if (uap->compat) {
333 				retval[1] = W_STOPCODE(p->p_xstat);
334 				error = 0;
335 			} else
336 #endif
337 			if (uap->status) {
338 				status = W_STOPCODE(p->p_xstat);
339 				error = copyout((caddr_t)&status,
340 				    (caddr_t)uap->status, sizeof(status));
341 			} else
342 				error = 0;
343 			return (error);
344 		}
345 	}
346 	if (nfound == 0)
347 		return (ECHILD);
348 	if (uap->options & WNOHANG) {
349 		retval[0] = 0;
350 		return (0);
351 	}
352 	if (error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0))
353 		return (error);
354 	goto loop;
355 }
356