kern_exit.c revision 3451
1234285Sdim/*-
2234285Sdim * Copyright (c) 1982, 1986, 1989, 1991, 1993
3234285Sdim *	The Regents of the University of California.  All rights reserved.
4234285Sdim * (c) UNIX System Laboratories, Inc.
5234285Sdim * All or some portions of this file are derived from material licensed
6234285Sdim * to the University of California by American Telephone and Telegraph
7234285Sdim * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8234285Sdim * the permission of UNIX System Laboratories, Inc.
9234285Sdim *
10234285Sdim * Redistribution and use in source and binary forms, with or without
11234285Sdim * modification, are permitted provided that the following conditions
12234285Sdim * are met:
13234285Sdim * 1. Redistributions of source code must retain the above copyright
14234285Sdim *    notice, this list of conditions and the following disclaimer.
15234285Sdim * 2. Redistributions in binary form must reproduce the above copyright
16234285Sdim *    notice, this list of conditions and the following disclaimer in the
17234285Sdim *    documentation and/or other materials provided with the distribution.
18234285Sdim * 3. All advertising materials mentioning features or use of this software
19251662Sdim *    must display the following acknowledgement:
20249423Sdim *	This product includes software developed by the University of
21251662Sdim *	California, Berkeley and its contributors.
22234285Sdim * 4. Neither the name of the University nor the names of its contributors
23234285Sdim *    may be used to endorse or promote products derived from this software
24234285Sdim *    without specific prior written permission.
25234285Sdim *
26234285Sdim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27234285Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28234285Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29263508Sdim * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30234285Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31263508Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32251662Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33251662Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34234285Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35234285Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36234285Sdim * SUCH DAMAGE.
37234285Sdim *
38234285Sdim *	@(#)kern_exit.c	8.7 (Berkeley) 2/12/94
39234285Sdim * $Id: kern_exit.c,v 1.8 1994/10/02 17:35:14 phk Exp $
40234285Sdim */
41234285Sdim
42234285Sdim#include <sys/param.h>
43234285Sdim#include <sys/systm.h>
44234285Sdim#include <sys/sysent.h>
45234285Sdim#include <sys/ioctl.h>
46234285Sdim#include <sys/proc.h>
47234285Sdim#include <sys/tty.h>
48234285Sdim#include <sys/time.h>
49234285Sdim#include <sys/resource.h>
50234285Sdim#include <sys/kernel.h>
51234285Sdim#include <sys/buf.h>
52234285Sdim#include <sys/wait.h>
53234285Sdim#include <sys/file.h>
54234285Sdim#include <sys/vnode.h>
55234285Sdim#include <sys/syslog.h>
56234285Sdim#include <sys/malloc.h>
57234285Sdim#include <sys/resourcevar.h>
58234285Sdim#include <sys/signalvar.h>
59234285Sdim#include <sys/ptrace.h>
60234285Sdim#include <sys/shm.h>
61234285Sdim#include <sys/filedesc.h>
62234285Sdim
63234285Sdim#include <machine/cpu.h>
64234285Sdim#ifdef COMPAT_43
65234285Sdim#include <machine/reg.h>
66234285Sdim#include <machine/psl.h>
67234285Sdim#endif
68234285Sdim
69234285Sdim#include <vm/vm.h>
70234285Sdim#include <vm/vm_kern.h>
71234285Sdim
72249423Sdim/*
73249423Sdim * exit --
74249423Sdim *	Death of process.
75249423Sdim */
76234285Sdimstruct rexit_args {
77234285Sdim	int	rval;
78234285Sdim};
79234285Sdim__dead void
80234285Sdimexit(p, uap, retval)
81234285Sdim	struct proc *p;
82234285Sdim	struct rexit_args *uap;
83234285Sdim	int *retval;
84234285Sdim{
85234285Sdim
86234285Sdim	exit1(p, W_EXITCODE(uap->rval, 0));
87234285Sdim	/* NOTREACHED */
88234285Sdim	while (1);
89234285Sdim}
90234285Sdim
91234285Sdim/*
92234285Sdim * Exit: deallocate address space and other resources, change proc state
93234285Sdim * to zombie, and unlink proc from allproc and parent's lists.  Save exit
94234285Sdim * status and rusage for wait().  Check for child processes and orphan them.
95234285Sdim */
96234285Sdim__dead void
97234285Sdimexit1(p, rv)
98234285Sdim	register struct proc *p;
99234285Sdim	int rv;
100234285Sdim{
101234285Sdim	register struct proc *q, *nq;
102234285Sdim	register struct proc **pp;
103234285Sdim	register struct vmspace *vm;
104234285Sdim
105234285Sdim	if (p->p_pid == 1)
106234285Sdim		panic("init died (signal %d, exit %d)",
107234285Sdim		    WTERMSIG(rv), WEXITSTATUS(rv));
108234285Sdim#ifdef PGINPROF
109234285Sdim	vmsizmon();
110234285Sdim#endif
111234285Sdim	if (p->p_flag & P_PROFIL)
112234285Sdim		stopprofclock(p);
113234285Sdim	MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage),
114234285Sdim		M_ZOMBIE, M_WAITOK);
115234285Sdim	/*
116234285Sdim	 * If parent is waiting for us to exit or exec,
117251662Sdim	 * P_PPWAIT is set; we will wakeup the parent below.
118234285Sdim	 */
119234285Sdim	p->p_flag &= ~(P_TRACED | P_PPWAIT);
120234285Sdim	p->p_flag |= P_WEXIT;
121234285Sdim	p->p_sigignore = ~0;
122234285Sdim	p->p_siglist = 0;
123239462Sdim	untimeout(realitexpire, (caddr_t)p);
124234285Sdim
125234285Sdim	/*
126234285Sdim	 * Close open files and release open-file table.
127234285Sdim	 * This may block!
128234285Sdim	 */
129234285Sdim	fdfree(p);
130234285Sdim
131234285Sdim	/* The next two chunks should probably be moved to vmspace_exit. */
132234285Sdim	vm = p->p_vmspace;
133234285Sdim#ifdef SYSVSHM
134251662Sdim	if (vm->vm_shm)
135251662Sdim		shmexit(p);
136251662Sdim#endif
137249423Sdim	/*
138251662Sdim	 * Release user portion of address space.
139234285Sdim	 * This releases references to vnodes,
140234285Sdim	 * which could cause I/O if the file has been unlinked.
141234285Sdim	 * Need to do this early enough that we can still sleep.
142234285Sdim	 * Can't free the entire vmspace as the kernel stack
143234285Sdim	 * may be mapped within that space also.
144234285Sdim	 */
145234285Sdim	if (vm->vm_refcnt == 1)
146234285Sdim		(void) vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS,
147234285Sdim		    VM_MAXUSER_ADDRESS);
148234285Sdim
149234285Sdim	if (SESS_LEADER(p)) {
150234285Sdim		register struct session *sp = p->p_session;
151234285Sdim
152234285Sdim		if (sp->s_ttyvp) {
153234285Sdim			/*
154234285Sdim			 * Controlling process.
155234285Sdim			 * Signal foreground pgrp,
156234285Sdim			 * drain controlling terminal
157234285Sdim			 * and revoke access to controlling terminal.
158234285Sdim			 */
159234285Sdim			if (sp->s_ttyp->t_session == sp) {
160234285Sdim				if (sp->s_ttyp->t_pgrp)
161234285Sdim					pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
162234285Sdim				(void) ttywait(sp->s_ttyp);
163234285Sdim				/*
164234285Sdim				 * The tty could have been revoked
165234285Sdim				 * if we blocked.
166234285Sdim				 */
167234285Sdim				if (sp->s_ttyvp)
168234285Sdim					vgoneall(sp->s_ttyvp);
169234285Sdim			}
170234285Sdim			if (sp->s_ttyvp)
171234285Sdim				vrele(sp->s_ttyvp);
172234285Sdim			sp->s_ttyvp = NULL;
173234285Sdim			/*
174234285Sdim			 * s_ttyp is not zero'd; we use this to indicate
175234285Sdim			 * that the session once had a controlling terminal.
176239462Sdim			 * (for logging and informational purposes)
177239462Sdim			 */
178234285Sdim		}
179234285Sdim		sp->s_leader = NULL;
180239462Sdim	}
181249423Sdim	fixjobc(p, p->p_pgrp, 0);
182251662Sdim	p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
183249423Sdim	(void)acct_process(p);
184263508Sdim#ifdef KTRACE
185263508Sdim	/*
186263508Sdim	 * release trace file
187263508Sdim	 */
188263508Sdim	p->p_traceflag = 0;	/* don't trace the vrele() */
189263508Sdim	if (p->p_tracep)
190234285Sdim		vrele(p->p_tracep);
191234285Sdim#endif
192239462Sdim	/*
193239462Sdim	 * Remove proc from allproc queue and pidhash chain.
194239462Sdim	 * Place onto zombproc.  Unlink from parent's child list.
195239462Sdim	 */
196263508Sdim	if ((*p->p_prev = p->p_next))
197239462Sdim		p->p_next->p_prev = p->p_prev;
198239462Sdim	if ((p->p_next = zombproc))
199234285Sdim		p->p_next->p_prev = &p->p_next;
200249423Sdim	p->p_prev = &zombproc;
201249423Sdim	zombproc = p;
202249423Sdim	p->p_stat = SZOMB;
203251662Sdim
204251662Sdim	for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash)
205249423Sdim		if (*pp == p) {
206249423Sdim			*pp = p->p_hash;
207249423Sdim			goto done;
208249423Sdim		}
209249423Sdim	panic("exit");
210249423Sdimdone:
211249423Sdim
212249423Sdim	if (p->p_cptr)		/* only need this if any child is S_ZOMB */
213251662Sdim		wakeup((caddr_t) initproc);
214251662Sdim	for (q = p->p_cptr; q != NULL; q = nq) {
215251662Sdim		nq = q->p_osptr;
216234285Sdim		if (nq != NULL)
217234285Sdim			nq->p_ysptr = NULL;
218234285Sdim		if (initproc->p_cptr)
219234285Sdim			initproc->p_cptr->p_ysptr = q;
220234285Sdim		q->p_osptr = initproc->p_cptr;
221234285Sdim		q->p_ysptr = NULL;
222234285Sdim		initproc->p_cptr = q;
223234285Sdim
224		q->p_pptr = initproc;
225		/*
226		 * Traced processes are killed
227		 * since their existence means someone is screwing up.
228		 */
229		if (q->p_flag & P_TRACED) {
230			q->p_flag &= ~P_TRACED;
231			psignal(q, SIGKILL);
232		}
233	}
234	p->p_cptr = NULL;
235
236	/*
237	 * Save exit status and final rusage info, adding in child rusage
238	 * info and self times.
239	 */
240	p->p_xstat = rv;
241	*p->p_ru = p->p_stats->p_ru;
242	calcru(p, &p->p_ru->ru_utime, &p->p_ru->ru_stime, NULL);
243	ruadd(p->p_ru, &p->p_stats->p_cru);
244
245	/*
246	 * Notify parent that we're gone.
247	 */
248	psignal(p->p_pptr, SIGCHLD);
249	wakeup((caddr_t)p->p_pptr);
250#if defined(tahoe)
251	/* move this to cpu_exit */
252	p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL;
253#endif
254	/*
255	 * Clear curproc after we've done all operations
256	 * that could block, and before tearing down the rest
257	 * of the process state that might be used from clock, etc.
258	 * Also, can't clear curproc while we're still runnable,
259	 * as we're not on a run queue (we are current, just not
260	 * a proper proc any longer!).
261	 *
262	 * Other substructures are freed from wait().
263	 */
264	curproc = NULL;
265	if (--p->p_limit->p_refcnt == 0)
266		FREE(p->p_limit, M_SUBPROC);
267
268	/*
269	 * Finally, call machine-dependent code to release the remaining
270	 * resources including address space, the kernel stack and pcb.
271	 * The address space is released by "vmspace_free(p->p_vmspace)";
272	 * This is machine-dependent, as we may have to change stacks
273	 * or ensure that the current one isn't reallocated before we
274	 * finish.  cpu_exit will end with a call to cpu_swtch(), finishing
275	 * our execution (pun intended).
276	 */
277	cpu_exit(p);
278}
279
280struct wait_args {
281	int	pid;
282	int	*status;
283	int	options;
284	struct	rusage *rusage;
285#if defined(COMPAT_43) || defined(IBCS2)
286	int	compat;		/* pseudo */
287#endif
288};
289
290#if defined(COMPAT_43) || defined(IBCS2)
291#if defined(hp300) || defined(luna68k)
292#include <machine/frame.h>
293#define GETPS(rp)	((struct frame *)(rp))->f_sr
294#else
295#define GETPS(rp)	(rp)[PS]
296#endif
297
298int
299owait(p, uap, retval)
300	struct proc *p;
301	register struct wait_args *uap;
302	int *retval;
303{
304
305#ifdef PSL_ALLCC
306	if ((GETPS(p->p_md.md_regs) & PSL_ALLCC) != PSL_ALLCC) {
307		uap->options = 0;
308		uap->rusage = NULL;
309	} else {
310		uap->options = p->p_md.md_regs[R0];
311		uap->rusage = (struct rusage *)p->p_md.md_regs[R1];
312	}
313#else
314	uap->options = 0;
315	uap->rusage = NULL;
316#endif
317	uap->pid = WAIT_ANY;
318	uap->status = NULL;
319	uap->compat = 1;
320	return (wait1(p, uap, retval));
321}
322
323int
324wait4(p, uap, retval)
325	struct proc *p;
326	struct wait_args *uap;
327	int *retval;
328{
329
330	uap->compat = 0;
331	return (wait1(p, uap, retval));
332}
333#else
334#define	wait1	wait4
335#endif
336
337int
338wait1(q, uap, retval)
339	register struct proc *q;
340	register struct wait_args *uap;
341	int retval[];
342{
343	register int nfound;
344	register struct proc *p, *t;
345	int status, error, sig;
346
347	if (uap->pid == 0)
348		uap->pid = -q->p_pgid;
349#ifdef notyet
350	if (uap->options &~ (WUNTRACED|WNOHANG))
351		return (EINVAL);
352#endif
353loop:
354	nfound = 0;
355	for (p = q->p_cptr; p; p = p->p_osptr) {
356		if (uap->pid != WAIT_ANY &&
357		    p->p_pid != uap->pid && p->p_pgid != -uap->pid)
358			continue;
359		nfound++;
360#if defined(COMPAT_43) || defined(IBCS2)
361		if (q->p_sysent->sv_sigtbl) {
362			if (p->p_xstat > q->p_sysent->sv_sigsize)
363				sig = q->p_sysent->sv_sigsize + 1;
364			else
365				sig = q->p_sysent->sv_sigtbl[p->p_xstat];
366		} else
367			sig = p->p_xstat;
368#endif
369		if (p->p_stat == SZOMB) {
370			/* charge childs scheduling cpu usage to parent */
371			if (curproc->p_pid != 1) {
372				curproc->p_estcpu = min(curproc->p_estcpu +
373				    p->p_estcpu, UCHAR_MAX);
374			}
375
376			retval[0] = p->p_pid;
377#if defined(COMPAT_43) || defined(IBCS2)
378			if (uap->compat)
379				retval[1] = sig;
380			else
381#endif
382			if (uap->status) {
383				status = p->p_xstat;	/* convert to int */
384				if ((error = copyout((caddr_t)&status,
385				    (caddr_t)uap->status, sizeof(status))))
386					return (error);
387			}
388			if (uap->rusage && (error = copyout((caddr_t)p->p_ru,
389			    (caddr_t)uap->rusage, sizeof (struct rusage))))
390				return (error);
391			/*
392			 * If we got the child via a ptrace 'attach',
393			 * we need to give it back to the old parent.
394			 */
395			if (p->p_oppid && (t = pfind(p->p_oppid))) {
396				p->p_oppid = 0;
397				proc_reparent(p, t);
398				psignal(t, SIGCHLD);
399				wakeup((caddr_t)t);
400				return (0);
401			}
402			p->p_xstat = 0;
403			ruadd(&q->p_stats->p_cru, p->p_ru);
404			FREE(p->p_ru, M_ZOMBIE);
405
406			/*
407			 * Decrement the count of procs running with this uid.
408			 */
409			(void)chgproccnt(p->p_cred->p_ruid, -1);
410
411			/*
412			 * Free up credentials.
413			 */
414			if (--p->p_cred->p_refcnt == 0) {
415				crfree(p->p_cred->pc_ucred);
416				FREE(p->p_cred, M_SUBPROC);
417			}
418
419			/*
420			 * Release reference to text vnode
421			 */
422			if (p->p_textvp)
423				vrele(p->p_textvp);
424
425			/*
426			 * Finally finished with old proc entry.
427			 * Unlink it from its process group and free it.
428			 */
429			leavepgrp(p);
430			if ((*p->p_prev = p->p_next))	/* off zombproc */
431				p->p_next->p_prev = p->p_prev;
432			if ((q = p->p_ysptr))
433				q->p_osptr = p->p_osptr;
434			if ((q = p->p_osptr))
435				q->p_ysptr = p->p_ysptr;
436			if ((q = p->p_pptr)->p_cptr == p)
437				q->p_cptr = p->p_osptr;
438
439			/*
440			 * Give machine-dependent layer a chance
441			 * to free anything that cpu_exit couldn't
442			 * release while still running in process context.
443			 */
444			cpu_wait(p);
445			FREE(p, M_PROC);
446			nprocs--;
447			return (0);
448		}
449		if (p->p_stat == SSTOP && (p->p_flag & P_WAITED) == 0 &&
450		    (p->p_flag & P_TRACED || uap->options & WUNTRACED)) {
451			p->p_flag |= P_WAITED;
452			retval[0] = p->p_pid;
453#if defined(COMPAT_43) || defined(IBCS2)
454			if (uap->compat) {
455				retval[1] = W_STOPCODE(sig);
456				error = 0;
457			} else
458#endif
459			if (uap->status) {
460				status = W_STOPCODE(p->p_xstat);
461				error = copyout((caddr_t)&status,
462					(caddr_t)uap->status, sizeof(status));
463			} else
464				error = 0;
465			return (error);
466		}
467	}
468	if (nfound == 0)
469		return (ECHILD);
470	if (uap->options & WNOHANG) {
471		retval[0] = 0;
472		return (0);
473	}
474	if ((error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0)))
475		return (error);
476	goto loop;
477}
478
479/*
480 * make process 'parent' the new parent of process 'child'.
481 */
482void
483proc_reparent(child, parent)
484	register struct proc *child;
485	register struct proc *parent;
486{
487	register struct proc *o;
488	register struct proc *y;
489
490	if (child->p_pptr == parent)
491		return;
492
493	/* fix up the child linkage for the old parent */
494	o = child->p_osptr;
495	y = child->p_ysptr;
496	if (y)
497		y->p_osptr = o;
498	if (o)
499		o->p_ysptr = y;
500	if (child->p_pptr->p_cptr == child)
501		child->p_pptr->p_cptr = o;
502
503	/* fix up child linkage for new parent */
504	o = parent->p_cptr;
505	if (o)
506		o->p_ysptr = child;
507	child->p_osptr = o;
508	child->p_ysptr = NULL;
509	parent->p_cptr = child;
510	child->p_pptr = parent;
511}
512