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