xref: /csrg-svn/sys/kern/kern_exit.c (revision 43380)
123369Smckusick /*
237728Smckusick  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
337728Smckusick  * All rights reserved.
423369Smckusick  *
537728Smckusick  * Redistribution and use in source and binary forms are permitted
637728Smckusick  * provided that the above copyright notice and this paragraph are
737728Smckusick  * duplicated in all such forms and that any documentation,
837728Smckusick  * advertising materials, and other materials related to such
937728Smckusick  * distribution and use acknowledge that the software was developed
1037728Smckusick  * by the University of California, Berkeley.  The name of the
1137728Smckusick  * University may not be used to endorse or promote products derived
1237728Smckusick  * from this software without specific prior written permission.
1337728Smckusick  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1437728Smckusick  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1537728Smckusick  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1637728Smckusick  *
17*43380Smckusick  *	@(#)kern_exit.c	7.23 (Berkeley) 06/21/90
1823369Smckusick  */
1912790Ssam 
2017090Sbloom #include "param.h"
2117090Sbloom #include "systm.h"
2217090Sbloom #include "map.h"
2342927Smckusick #include "ioctl.h"
2442927Smckusick #include "tty.h"
2542927Smckusick #undef RETURN
2642927Smckusick #include "syscontext.h"
2717090Sbloom #include "kernel.h"
2817090Sbloom #include "proc.h"
2917090Sbloom #include "buf.h"
3017090Sbloom #include "wait.h"
3117090Sbloom #include "vm.h"
3217090Sbloom #include "file.h"
3337728Smckusick #include "vnode.h"
3418638Ssam #include "syslog.h"
3532018Smckusick #include "malloc.h"
3612790Ssam 
3737520Smckusick #include "machine/reg.h"
3837328Skarels #ifdef COMPAT_43
3937520Smckusick #include "machine/psl.h"
4037328Skarels #endif
4137328Skarels 
4212790Ssam /*
4312790Ssam  * Exit system call: pass back caller's arg
4412790Ssam  */
4542927Smckusick /* ARGSUSED */
4642927Smckusick rexit(p, uap, retval)
4742927Smckusick 	struct proc *p;
4842927Smckusick 	struct args {
4912790Ssam 		int	rval;
5012790Ssam 	} *uap;
5142927Smckusick 	int *retval;
5242927Smckusick {
5312790Ssam 
5442927Smckusick 	RETURN (exit(p, W_EXITCODE(uap->rval, 0)));
5512790Ssam }
5612790Ssam 
5712790Ssam /*
5812790Ssam  * Release resources.
5912790Ssam  * Save u. area for parent to look at.
6012790Ssam  * Enter zombie state.
6112790Ssam  * Wake up parent and init processes,
6212790Ssam  * and dispose of children.
6312790Ssam  */
6442927Smckusick exit(p, rv)
6542927Smckusick 	struct proc *p;
6638930Skarels 	int rv;
6712790Ssam {
6812790Ssam 	register int i;
6942927Smckusick 	register struct proc *q, *nq;
7040670Skarels 	register struct proc **pp;
7112790Ssam 
7212790Ssam #ifdef PGINPROF
7312790Ssam 	vmsizmon();
7412790Ssam #endif
7532018Smckusick 	MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage),
7632018Smckusick 		M_ZOMBIE, M_WAITOK);
7712790Ssam 	p->p_flag &= ~(STRC|SULOCK);
7812790Ssam 	p->p_flag |= SWEXIT;
7912882Ssam 	p->p_sigignore = ~0;
8039410Skarels 	p->p_sig = 0;
8112790Ssam 	p->p_cpticks = 0;
8212790Ssam 	p->p_pctcpu = 0;
8312882Ssam 	for (i = 0; i < NSIG; i++)
8412790Ssam 		u.u_signal[i] = SIG_IGN;
8512790Ssam 	untimeout(realitexpire, (caddr_t)p);
8612790Ssam 	/*
8712790Ssam 	 * Release virtual memory.  If we resulted from
8812790Ssam 	 * a vfork(), instead give the resources back to
8912790Ssam 	 * the parent.
9012790Ssam 	 */
9141569Smckusick 	if ((p->p_flag & SVFORK) == 0) {
9241569Smckusick #ifdef MAPMEM
9341569Smckusick 		if (u.u_mmap)
9442927Smckusick 			(void) mmexit(p);
9541569Smckusick #endif
9612790Ssam 		vrelvm();
9741569Smckusick 	} else {
9812790Ssam 		p->p_flag &= ~SVFORK;
9912790Ssam 		wakeup((caddr_t)p);
10012790Ssam 		while ((p->p_flag & SVFDONE) == 0)
10112790Ssam 			sleep((caddr_t)p, PZERO - 1);
10212790Ssam 		p->p_flag &= ~SVFDONE;
10312790Ssam 	}
10421105Skarels 	for (i = 0; i <= u.u_lastfile; i++) {
10512790Ssam 		struct file *f;
10612790Ssam 
10712790Ssam 		f = u.u_ofile[i];
10821105Skarels 		if (f) {
10921105Skarels 			u.u_ofile[i] = NULL;
11021105Skarels 			u.u_pofile[i] = 0;
11139351Smckusick 			(void) closef(f);
11221105Skarels 		}
11312790Ssam 	}
11437328Skarels 	if (SESS_LEADER(p)) {
11542897Smarc 		register struct session *sp = p->p_session;
11642897Smarc 
11742897Smarc 		if (sp->s_ttyvp) {
11840809Smarc 			/*
11942897Smarc 			 * Controlling process.
12042897Smarc 			 * Signal foreground pgrp and revoke access
12142897Smarc 			 * to controlling terminal.
12242897Smarc 			 */
12342897Smarc 			if (sp->s_ttyp->t_pgrp)
12442916Smarc 				pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
12542897Smarc 			vgoneall(sp->s_ttyvp);
12642897Smarc 			vrele(sp->s_ttyvp);
12742897Smarc 			sp->s_ttyvp = NULL;
12842897Smarc 			/*
12940809Smarc 			 * s_ttyp is not zero'd; we use this to indicate
13040809Smarc 			 * that the session once had a controlling terminal.
13142897Smarc 			 * (for logging and informational purposes)
13240809Smarc 			 */
13337328Skarels 		}
13442897Smarc 		sp->s_leader = 0;
13537328Skarels 	}
13637728Smckusick 	VOP_LOCK(u.u_cdir);
13737728Smckusick 	vput(u.u_cdir);
13812790Ssam 	if (u.u_rdir) {
13937728Smckusick 		VOP_LOCK(u.u_rdir);
14037728Smckusick 		vput(u.u_rdir);
14112790Ssam 	}
14212790Ssam 	u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
143*43380Smckusick 	(void) acct(p);
14437728Smckusick 	crfree(u.u_cred);
14537328Skarels #ifdef KTRACE
14637328Skarels 	/*
14737328Skarels 	 * release trace file
14837328Skarels 	 */
14937328Skarels 	if (p->p_tracep)
15037728Smckusick 		vrele(p->p_tracep);
15137328Skarels #endif
15226823Skarels 	/*
15326823Skarels 	 * Freeing the user structure and kernel stack
15426823Skarels 	 * for the current process: have to run a bit longer
15526823Skarels 	 * using the pages which are about to be freed...
15626823Skarels 	 * vrelu will block memory allocation by raising ipl.
15726823Skarels 	 */
15842927Smckusick 	vrelu(p, 0);
15942927Smckusick 	vrelpt(p);
16016527Skarels 	if (*p->p_prev = p->p_nxt)		/* off allproc queue */
16116527Skarels 		p->p_nxt->p_prev = p->p_prev;
16216527Skarels 	if (p->p_nxt = zombproc)		/* onto zombproc */
16316527Skarels 		p->p_nxt->p_prev = &p->p_nxt;
16416527Skarels 	p->p_prev = &zombproc;
16516527Skarels 	zombproc = p;
16612790Ssam 	multprog--;
16712790Ssam 	p->p_stat = SZOMB;
16812790Ssam 	noproc = 1;
16940670Skarels 	for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash)
17040670Skarels 		if (*pp == p) {
17140670Skarels 			*pp = p->p_hash;
17240670Skarels 			goto done;
17340670Skarels 		}
17440670Skarels 	panic("exit");
17540670Skarels done:
17621105Skarels 	if (p->p_pid == 1) {
17721105Skarels 		if (p->p_dsize == 0) {
17839410Skarels 			printf("Can't exec init (errno %d)\n", WEXITSTATUS(rv));
17921105Skarels 			for (;;)
18021105Skarels 				;
18121105Skarels 		} else
18221105Skarels 			panic("init died");
18321105Skarels 	}
18412790Ssam 	p->p_xstat = rv;
18521105Skarels 	*p->p_ru = u.u_ru;
18640809Smarc 	i = splclock();
18740809Smarc 	p->p_ru->ru_stime = p->p_stime;
18840809Smarc 	p->p_ru->ru_utime = p->p_utime;
18940809Smarc 	splx(i);
19021105Skarels 	ruadd(p->p_ru, &u.u_cru);
19116527Skarels 	if (p->p_cptr)		/* only need this if any child is S_ZOMB */
19216527Skarels 		wakeup((caddr_t)&proc[1]);
19342897Smarc 	fixjobc(p, 0);
19416527Skarels 	for (q = p->p_cptr; q != NULL; q = nq) {
19516527Skarels 		nq = q->p_osptr;
19616527Skarels 		if (nq != NULL)
19716527Skarels 			nq->p_ysptr = NULL;
19816527Skarels 		if (proc[1].p_cptr)
19916527Skarels 			proc[1].p_cptr->p_ysptr = q;
20016527Skarels 		q->p_osptr = proc[1].p_cptr;
20116527Skarels 		q->p_ysptr = NULL;
20216527Skarels 		proc[1].p_cptr = q;
20312790Ssam 
20416527Skarels 		q->p_pptr = &proc[1];
20516527Skarels 		q->p_ppid = 1;
20616527Skarels 		/*
20716527Skarels 		 * Traced processes are killed
20816527Skarels 		 * since their existence means someone is screwing up.
20916527Skarels 		 */
21016527Skarels 		if (q->p_flag&STRC) {
21116527Skarels 			q->p_flag &= ~STRC;
21216527Skarels 			psignal(q, SIGKILL);
21312790Ssam 		}
21416527Skarels 	}
21517540Skarels 	p->p_cptr = NULL;
21612790Ssam 	psignal(p->p_pptr, SIGCHLD);
21712790Ssam 	wakeup((caddr_t)p->p_pptr);
21829946Skarels #if defined(tahoe)
21929946Skarels 	dkeyrelease(p->p_dkey), p->p_dkey = 0;
22029946Skarels 	ckeyrelease(p->p_ckey), p->p_ckey = 0;
22129946Skarels 	u.u_pcb.pcb_savacc.faddr = (float *)NULL;
22229946Skarels #endif
22312790Ssam 	swtch();
22412790Ssam }
22512790Ssam 
22637328Skarels #ifdef COMPAT_43
22742927Smckusick owait(p, uap, retval)
22842927Smckusick 	struct proc *p;
22942927Smckusick 	register struct args {
23037328Skarels 		int	pid;
23139410Skarels 		int	*status;
23237328Skarels 		int	options;
23337328Skarels 		struct	rusage *rusage;
23439410Skarels 		int	compat;
23542927Smckusick 	} *uap;
23642927Smckusick 	int *retval;
23742927Smckusick {
23812790Ssam 
23912790Ssam 	if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) {
24038930Skarels 		uap->options = 0;
24137328Skarels 		uap->rusage = 0;
24237328Skarels 	} else {
24338930Skarels 		uap->options = u.u_ar0[R0];
24437328Skarels 		uap->rusage = (struct rusage *)u.u_ar0[R1];
24512790Ssam 	}
24637328Skarels 	uap->pid = WAIT_ANY;
24737328Skarels 	uap->status = 0;
24839410Skarels 	uap->compat = 1;
24942927Smckusick 	RETURN (wait1(p, uap, retval));
25012790Ssam }
25112790Ssam 
25242927Smckusick wait4(p, uap, retval)
25342927Smckusick 	struct proc *p;
25442927Smckusick 	struct args {
25539410Skarels 		int	pid;
25639410Skarels 		int	*status;
25739410Skarels 		int	options;
25839410Skarels 		struct	rusage *rusage;
25939410Skarels 		int	compat;
26042927Smckusick 	} *uap;
26142927Smckusick 	int *retval;
26242927Smckusick {
26339410Skarels 
26439410Skarels 	uap->compat = 0;
26542927Smckusick 	RETURN (wait1(p, uap, retval));
26637328Skarels }
26739410Skarels #else
26839410Skarels #define	wait1	wait4
26937328Skarels #endif
27037328Skarels 
27112790Ssam /*
27212790Ssam  * Wait system call.
27312790Ssam  * Search for a terminated (zombie) child,
27412790Ssam  * finally lay it to rest, and collect its status.
27512790Ssam  * Look also for stopped (traced) children,
27612790Ssam  * and pass back status from them.
27712790Ssam  */
27842927Smckusick wait1(q, uap, retval)
27942927Smckusick 	register struct proc *q;
28042927Smckusick 	register struct args {
28137328Skarels 		int	pid;
28239410Skarels 		int	*status;
28337328Skarels 		int	options;
28437328Skarels 		struct	rusage *rusage;
28539410Skarels #ifdef COMPAT_43
28639410Skarels 		int compat;
28739410Skarels #endif
28842927Smckusick 	} *uap;
28942927Smckusick 	int retval[];
29042927Smckusick {
29142927Smckusick 	register int f;
29242927Smckusick 	register struct proc *p;
29339410Skarels 	int status, error;
29412790Ssam 
29537328Skarels 	if (uap->pid == 0)
29637328Skarels 		uap->pid = -q->p_pgid;
29738930Skarels #ifdef notyet
29839410Skarels 	if (uap->options &~ (WUNTRACED|WNOHANG))
29942927Smckusick 		RETURN (EINVAL);
30038930Skarels #endif
30112790Ssam loop:
30238930Skarels 	f = 0;
30316527Skarels 	for (p = q->p_cptr; p; p = p->p_osptr) {
30437328Skarels 		if (uap->pid != WAIT_ANY &&
30537328Skarels 		    p->p_pid != uap->pid && p->p_pgid != -uap->pid)
30637328Skarels 			continue;
30712790Ssam 		f++;
30812790Ssam 		if (p->p_stat == SZOMB) {
30942927Smckusick 			retval[0] = p->p_pid;
31037328Skarels #ifdef COMPAT_43
31139410Skarels 			if (uap->compat)
31242927Smckusick 				retval[1] = p->p_xstat;
31337328Skarels 			else
31437328Skarels #endif
31537328Skarels 			if (uap->status) {
31639410Skarels 				status = p->p_xstat;	/* convert to int */
31739410Skarels 				if (error = copyout((caddr_t)&status,
31837328Skarels 				    (caddr_t)uap->status, sizeof(status)))
31942927Smckusick 					RETURN (error);
32037328Skarels 			}
32139410Skarels 			if (uap->rusage && (error = copyout((caddr_t)p->p_ru,
32239410Skarels 			    (caddr_t)uap->rusage, sizeof (struct rusage))))
32342927Smckusick 				RETURN (error);
32439410Skarels 			pgrm(p);			/* off pgrp */
32512790Ssam 			p->p_xstat = 0;
32637328Skarels 			ruadd(&u.u_cru, p->p_ru);
32737328Skarels 			FREE(p->p_ru, M_ZOMBIE);
32837328Skarels 			p->p_ru = 0;
32912790Ssam 			p->p_stat = NULL;
33012790Ssam 			p->p_pid = 0;
33112790Ssam 			p->p_ppid = 0;
33216527Skarels 			if (*p->p_prev = p->p_nxt)	/* off zombproc */
33316527Skarels 				p->p_nxt->p_prev = p->p_prev;
33416527Skarels 			p->p_nxt = freeproc;		/* onto freeproc */
33516527Skarels 			freeproc = p;
33612790Ssam 			if (q = p->p_ysptr)
33712790Ssam 				q->p_osptr = p->p_osptr;
33812790Ssam 			if (q = p->p_osptr)
33912790Ssam 				q->p_ysptr = p->p_ysptr;
34012790Ssam 			if ((q = p->p_pptr)->p_cptr == p)
34112790Ssam 				q->p_cptr = p->p_osptr;
34212790Ssam 			p->p_pptr = 0;
34312790Ssam 			p->p_ysptr = 0;
34412790Ssam 			p->p_osptr = 0;
34512790Ssam 			p->p_cptr = 0;
34612790Ssam 			p->p_sig = 0;
34712882Ssam 			p->p_sigcatch = 0;
34812882Ssam 			p->p_sigignore = 0;
34912882Ssam 			p->p_sigmask = 0;
35037328Skarels 			/*p->p_pgrp = 0;*/
35112790Ssam 			p->p_flag = 0;
35212790Ssam 			p->p_wchan = 0;
35312790Ssam 			p->p_cursig = 0;
35442927Smckusick 			RETURN (0);
35512790Ssam 		}
35637328Skarels 		if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 &&
35737328Skarels 		    (p->p_flag & STRC || uap->options & WUNTRACED)) {
35812790Ssam 			p->p_flag |= SWTED;
35942927Smckusick 			retval[0] = p->p_pid;
36037328Skarels #ifdef COMPAT_43
36139737Smckusick 			if (uap->compat) {
36242927Smckusick 				retval[1] = W_STOPCODE(p->p_cursig);
36339737Smckusick 				error = 0;
36439737Smckusick 			} else
36537328Skarels #endif
36637328Skarels 			if (uap->status) {
36739410Skarels 				status = W_STOPCODE(p->p_cursig);
36839410Skarels 				error = copyout((caddr_t)&status,
36937328Skarels 				    (caddr_t)uap->status, sizeof(status));
37039410Skarels 			} else
37139410Skarels 				error = 0;
37242927Smckusick 			RETURN (error);
37312790Ssam 		}
37412790Ssam 	}
37539410Skarels 	if (f == 0)
37642927Smckusick 		RETURN (ECHILD);
37737328Skarels 	if (uap->options & WNOHANG) {
37842927Smckusick 		retval[0] = 0;
37942927Smckusick 		RETURN (0);
38012790Ssam 	}
38142927Smckusick 	if (error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0))
38242927Smckusick 		RETURN (error);
38312790Ssam 	goto loop;
38412790Ssam }
385