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