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