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