xref: /csrg-svn/sys/kern/kern_exit.c (revision 45739)
123369Smckusick /*
237728Smckusick  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
337728Smckusick  * All rights reserved.
423369Smckusick  *
544433Sbostic  * %sccs.include.redist.c%
637728Smckusick  *
7*45739Smckusick  *	@(#)kern_exit.c	7.29 (Berkeley) 12/05/90
823369Smckusick  */
912790Ssam 
1017090Sbloom #include "param.h"
1117090Sbloom #include "systm.h"
1217090Sbloom #include "map.h"
1342927Smckusick #include "ioctl.h"
1442927Smckusick #include "tty.h"
1544404Skarels #include "user.h"
1617090Sbloom #include "kernel.h"
1717090Sbloom #include "proc.h"
1817090Sbloom #include "buf.h"
1917090Sbloom #include "wait.h"
2017090Sbloom #include "file.h"
2137728Smckusick #include "vnode.h"
2218638Ssam #include "syslog.h"
2332018Smckusick #include "malloc.h"
2412790Ssam 
2537520Smckusick #include "machine/reg.h"
2637328Skarels #ifdef COMPAT_43
2737520Smckusick #include "machine/psl.h"
2837328Skarels #endif
2937328Skarels 
30*45739Smckusick #include "../vm/vm_param.h"
31*45739Smckusick #include "../vm/vm_map.h"
32*45739Smckusick #include "../vm/vm_kern.h"
33*45739Smckusick 
3412790Ssam /*
3512790Ssam  * Exit system call: pass back caller's arg
3612790Ssam  */
3742927Smckusick /* ARGSUSED */
3842927Smckusick rexit(p, uap, retval)
3942927Smckusick 	struct proc *p;
4042927Smckusick 	struct args {
4112790Ssam 		int	rval;
4212790Ssam 	} *uap;
4342927Smckusick 	int *retval;
4442927Smckusick {
4512790Ssam 
4645157Skarels 	exit(p, W_EXITCODE(uap->rval, 0));
4745157Skarels 	/* NOTREACHED */
4812790Ssam }
4912790Ssam 
5012790Ssam /*
5112790Ssam  * Release resources.
5212790Ssam  * Save u. area for parent to look at.
5312790Ssam  * Enter zombie state.
5412790Ssam  * Wake up parent and init processes,
5512790Ssam  * and dispose of children.
5612790Ssam  */
5742927Smckusick exit(p, rv)
5842927Smckusick 	struct proc *p;
5938930Skarels 	int rv;
6012790Ssam {
6112790Ssam 	register int i;
6242927Smckusick 	register struct proc *q, *nq;
6340670Skarels 	register struct proc **pp;
6412790Ssam 
6512790Ssam #ifdef PGINPROF
6612790Ssam 	vmsizmon();
6712790Ssam #endif
6832018Smckusick 	MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage),
6932018Smckusick 		M_ZOMBIE, M_WAITOK);
7012790Ssam 	p->p_flag &= ~(STRC|SULOCK);
7112790Ssam 	p->p_flag |= SWEXIT;
7212882Ssam 	p->p_sigignore = ~0;
7339410Skarels 	p->p_sig = 0;
7412790Ssam 	p->p_cpticks = 0;
7512790Ssam 	p->p_pctcpu = 0;
7612882Ssam 	for (i = 0; i < NSIG; i++)
7712790Ssam 		u.u_signal[i] = SIG_IGN;
7812790Ssam 	untimeout(realitexpire, (caddr_t)p);
79*45739Smckusick #ifdef SYSVSHM
80*45739Smckusick 	if (p->p_shm)
81*45739Smckusick 		shmexit(p);
82*45739Smckusick #endif
83*45739Smckusick 	vm_map_deallocate(p->p_map);
84*45739Smckusick 	p->p_map = VM_MAP_NULL;
8512790Ssam 	/*
86*45739Smckusick 	 * XXX preserve synchronization semantics of vfork
8712790Ssam 	 */
88*45739Smckusick 	if (p->p_flag & SVFORK) {
8912790Ssam 		p->p_flag &= ~SVFORK;
9012790Ssam 		wakeup((caddr_t)p);
9112790Ssam 		while ((p->p_flag & SVFDONE) == 0)
9212790Ssam 			sleep((caddr_t)p, PZERO - 1);
9312790Ssam 		p->p_flag &= ~SVFDONE;
9412790Ssam 	}
9521105Skarels 	for (i = 0; i <= u.u_lastfile; i++) {
9612790Ssam 		struct file *f;
9712790Ssam 
9812790Ssam 		f = u.u_ofile[i];
9921105Skarels 		if (f) {
10021105Skarels 			u.u_ofile[i] = NULL;
10121105Skarels 			u.u_pofile[i] = 0;
10239351Smckusick 			(void) closef(f);
10321105Skarels 		}
10412790Ssam 	}
10537328Skarels 	if (SESS_LEADER(p)) {
10642897Smarc 		register struct session *sp = p->p_session;
10742897Smarc 
10842897Smarc 		if (sp->s_ttyvp) {
10940809Smarc 			/*
11042897Smarc 			 * Controlling process.
11142897Smarc 			 * Signal foreground pgrp and revoke access
11242897Smarc 			 * to controlling terminal.
11342897Smarc 			 */
11442897Smarc 			if (sp->s_ttyp->t_pgrp)
11542916Smarc 				pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
11642897Smarc 			vgoneall(sp->s_ttyvp);
11742897Smarc 			vrele(sp->s_ttyvp);
11842897Smarc 			sp->s_ttyvp = NULL;
11942897Smarc 			/*
12040809Smarc 			 * s_ttyp is not zero'd; we use this to indicate
12140809Smarc 			 * that the session once had a controlling terminal.
12242897Smarc 			 * (for logging and informational purposes)
12340809Smarc 			 */
12437328Skarels 		}
12542897Smarc 		sp->s_leader = 0;
12637328Skarels 	}
12737728Smckusick 	VOP_LOCK(u.u_cdir);
12837728Smckusick 	vput(u.u_cdir);
12912790Ssam 	if (u.u_rdir) {
13037728Smckusick 		VOP_LOCK(u.u_rdir);
13137728Smckusick 		vput(u.u_rdir);
13212790Ssam 	}
13312790Ssam 	u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
13443380Smckusick 	(void) acct(p);
13537728Smckusick 	crfree(u.u_cred);
13637328Skarels #ifdef KTRACE
13737328Skarels 	/*
13837328Skarels 	 * release trace file
13937328Skarels 	 */
14037328Skarels 	if (p->p_tracep)
14137728Smckusick 		vrele(p->p_tracep);
14237328Skarels #endif
143*45739Smckusick 	splimp();
144*45739Smckusick 	/* I don't think this will cause a sleep/realloc anywhere... */
145*45739Smckusick 	kmem_free(kernel_map, (vm_offset_t)p->p_addr,
146*45739Smckusick 		  round_page(ctob(UPAGES)));
14716527Skarels 	if (*p->p_prev = p->p_nxt)		/* off allproc queue */
14816527Skarels 		p->p_nxt->p_prev = p->p_prev;
14916527Skarels 	if (p->p_nxt = zombproc)		/* onto zombproc */
15016527Skarels 		p->p_nxt->p_prev = &p->p_nxt;
15116527Skarels 	p->p_prev = &zombproc;
15216527Skarels 	zombproc = p;
15312790Ssam 	p->p_stat = SZOMB;
15412790Ssam 	noproc = 1;
15540670Skarels 	for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash)
15640670Skarels 		if (*pp == p) {
15740670Skarels 			*pp = p->p_hash;
15840670Skarels 			goto done;
15940670Skarels 		}
16040670Skarels 	panic("exit");
16140670Skarels done:
162*45739Smckusick 	if (p->p_pid == 1)
163*45739Smckusick 		panic("init died");
16412790Ssam 	p->p_xstat = rv;
16521105Skarels 	*p->p_ru = u.u_ru;
16640809Smarc 	i = splclock();
16740809Smarc 	p->p_ru->ru_stime = p->p_stime;
16840809Smarc 	p->p_ru->ru_utime = p->p_utime;
16940809Smarc 	splx(i);
17021105Skarels 	ruadd(p->p_ru, &u.u_cru);
17116527Skarels 	if (p->p_cptr)		/* only need this if any child is S_ZOMB */
17216527Skarels 		wakeup((caddr_t)&proc[1]);
17345673Skarels 	fixjobc(p, p->p_pgrp, 0);
17416527Skarels 	for (q = p->p_cptr; q != NULL; q = nq) {
17516527Skarels 		nq = q->p_osptr;
17616527Skarels 		if (nq != NULL)
17716527Skarels 			nq->p_ysptr = NULL;
17816527Skarels 		if (proc[1].p_cptr)
17916527Skarels 			proc[1].p_cptr->p_ysptr = q;
18016527Skarels 		q->p_osptr = proc[1].p_cptr;
18116527Skarels 		q->p_ysptr = NULL;
18216527Skarels 		proc[1].p_cptr = q;
18312790Ssam 
18416527Skarels 		q->p_pptr = &proc[1];
18516527Skarels 		q->p_ppid = 1;
18616527Skarels 		/*
18716527Skarels 		 * Traced processes are killed
18816527Skarels 		 * since their existence means someone is screwing up.
18916527Skarels 		 */
19016527Skarels 		if (q->p_flag&STRC) {
19116527Skarels 			q->p_flag &= ~STRC;
19216527Skarels 			psignal(q, SIGKILL);
19312790Ssam 		}
19416527Skarels 	}
19517540Skarels 	p->p_cptr = NULL;
19612790Ssam 	psignal(p->p_pptr, SIGCHLD);
19712790Ssam 	wakeup((caddr_t)p->p_pptr);
19829946Skarels #if defined(tahoe)
19929946Skarels 	dkeyrelease(p->p_dkey), p->p_dkey = 0;
20029946Skarels 	ckeyrelease(p->p_ckey), p->p_ckey = 0;
20129946Skarels 	u.u_pcb.pcb_savacc.faddr = (float *)NULL;
20229946Skarels #endif
20312790Ssam 	swtch();
20412790Ssam }
20512790Ssam 
20637328Skarels #ifdef COMPAT_43
20742927Smckusick owait(p, uap, retval)
20842927Smckusick 	struct proc *p;
20942927Smckusick 	register struct args {
21037328Skarels 		int	pid;
21139410Skarels 		int	*status;
21237328Skarels 		int	options;
21337328Skarels 		struct	rusage *rusage;
21439410Skarels 		int	compat;
21542927Smckusick 	} *uap;
21642927Smckusick 	int *retval;
21742927Smckusick {
21812790Ssam 
21912790Ssam 	if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) {
22038930Skarels 		uap->options = 0;
22137328Skarels 		uap->rusage = 0;
22237328Skarels 	} else {
22338930Skarels 		uap->options = u.u_ar0[R0];
22437328Skarels 		uap->rusage = (struct rusage *)u.u_ar0[R1];
22512790Ssam 	}
22637328Skarels 	uap->pid = WAIT_ANY;
22737328Skarels 	uap->status = 0;
22839410Skarels 	uap->compat = 1;
22944404Skarels 	return (wait1(p, uap, retval));
23012790Ssam }
23112790Ssam 
23242927Smckusick wait4(p, uap, retval)
23342927Smckusick 	struct proc *p;
23442927Smckusick 	struct args {
23539410Skarels 		int	pid;
23639410Skarels 		int	*status;
23739410Skarels 		int	options;
23839410Skarels 		struct	rusage *rusage;
23939410Skarels 		int	compat;
24042927Smckusick 	} *uap;
24142927Smckusick 	int *retval;
24242927Smckusick {
24339410Skarels 
24439410Skarels 	uap->compat = 0;
24544404Skarels 	return (wait1(p, uap, retval));
24637328Skarels }
24739410Skarels #else
24839410Skarels #define	wait1	wait4
24937328Skarels #endif
25037328Skarels 
25112790Ssam /*
25212790Ssam  * Wait system call.
25312790Ssam  * Search for a terminated (zombie) child,
25412790Ssam  * finally lay it to rest, and collect its status.
25512790Ssam  * Look also for stopped (traced) children,
25612790Ssam  * and pass back status from them.
25712790Ssam  */
25842927Smckusick wait1(q, uap, retval)
25942927Smckusick 	register struct proc *q;
26042927Smckusick 	register struct args {
26137328Skarels 		int	pid;
26239410Skarels 		int	*status;
26337328Skarels 		int	options;
26437328Skarels 		struct	rusage *rusage;
26539410Skarels #ifdef COMPAT_43
26639410Skarels 		int compat;
26739410Skarels #endif
26842927Smckusick 	} *uap;
26942927Smckusick 	int retval[];
27042927Smckusick {
27142927Smckusick 	register int f;
27242927Smckusick 	register struct proc *p;
27339410Skarels 	int status, error;
27412790Ssam 
27537328Skarels 	if (uap->pid == 0)
27637328Skarels 		uap->pid = -q->p_pgid;
27738930Skarels #ifdef notyet
27839410Skarels 	if (uap->options &~ (WUNTRACED|WNOHANG))
27944404Skarels 		return (EINVAL);
28038930Skarels #endif
28112790Ssam loop:
28238930Skarels 	f = 0;
28316527Skarels 	for (p = q->p_cptr; p; p = p->p_osptr) {
28437328Skarels 		if (uap->pid != WAIT_ANY &&
28537328Skarels 		    p->p_pid != uap->pid && p->p_pgid != -uap->pid)
28637328Skarels 			continue;
28712790Ssam 		f++;
28812790Ssam 		if (p->p_stat == SZOMB) {
28942927Smckusick 			retval[0] = p->p_pid;
29037328Skarels #ifdef COMPAT_43
29139410Skarels 			if (uap->compat)
29242927Smckusick 				retval[1] = p->p_xstat;
29337328Skarels 			else
29437328Skarels #endif
29537328Skarels 			if (uap->status) {
29639410Skarels 				status = p->p_xstat;	/* convert to int */
29739410Skarels 				if (error = copyout((caddr_t)&status,
29837328Skarels 				    (caddr_t)uap->status, sizeof(status)))
29944404Skarels 					return (error);
30037328Skarels 			}
30139410Skarels 			if (uap->rusage && (error = copyout((caddr_t)p->p_ru,
30239410Skarels 			    (caddr_t)uap->rusage, sizeof (struct rusage))))
30344404Skarels 				return (error);
30439410Skarels 			pgrm(p);			/* off pgrp */
30512790Ssam 			p->p_xstat = 0;
30637328Skarels 			ruadd(&u.u_cru, p->p_ru);
30737328Skarels 			FREE(p->p_ru, M_ZOMBIE);
30837328Skarels 			p->p_ru = 0;
30912790Ssam 			p->p_stat = NULL;
31012790Ssam 			p->p_pid = 0;
31112790Ssam 			p->p_ppid = 0;
31216527Skarels 			if (*p->p_prev = p->p_nxt)	/* off zombproc */
31316527Skarels 				p->p_nxt->p_prev = p->p_prev;
31416527Skarels 			p->p_nxt = freeproc;		/* onto freeproc */
31516527Skarels 			freeproc = p;
31612790Ssam 			if (q = p->p_ysptr)
31712790Ssam 				q->p_osptr = p->p_osptr;
31812790Ssam 			if (q = p->p_osptr)
31912790Ssam 				q->p_ysptr = p->p_ysptr;
32012790Ssam 			if ((q = p->p_pptr)->p_cptr == p)
32112790Ssam 				q->p_cptr = p->p_osptr;
32212790Ssam 			p->p_pptr = 0;
32312790Ssam 			p->p_ysptr = 0;
32412790Ssam 			p->p_osptr = 0;
32512790Ssam 			p->p_cptr = 0;
32612790Ssam 			p->p_sig = 0;
32712882Ssam 			p->p_sigcatch = 0;
32812882Ssam 			p->p_sigignore = 0;
32912882Ssam 			p->p_sigmask = 0;
33037328Skarels 			/*p->p_pgrp = 0;*/
33112790Ssam 			p->p_flag = 0;
33212790Ssam 			p->p_wchan = 0;
33344404Skarels 			return (0);
33412790Ssam 		}
33537328Skarels 		if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 &&
33637328Skarels 		    (p->p_flag & STRC || uap->options & WUNTRACED)) {
33712790Ssam 			p->p_flag |= SWTED;
33842927Smckusick 			retval[0] = p->p_pid;
33937328Skarels #ifdef COMPAT_43
34039737Smckusick 			if (uap->compat) {
34143895Skarels 				retval[1] = W_STOPCODE(p->p_xstat);
34239737Smckusick 				error = 0;
34339737Smckusick 			} else
34437328Skarels #endif
34537328Skarels 			if (uap->status) {
34643895Skarels 				status = W_STOPCODE(p->p_xstat);
34739410Skarels 				error = copyout((caddr_t)&status,
34837328Skarels 				    (caddr_t)uap->status, sizeof(status));
34939410Skarels 			} else
35039410Skarels 				error = 0;
35144404Skarels 			return (error);
35212790Ssam 		}
35312790Ssam 	}
35439410Skarels 	if (f == 0)
35544404Skarels 		return (ECHILD);
35637328Skarels 	if (uap->options & WNOHANG) {
35742927Smckusick 		retval[0] = 0;
35844404Skarels 		return (0);
35912790Ssam 	}
36042927Smckusick 	if (error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0))
36144404Skarels 		return (error);
36212790Ssam 	goto loop;
36312790Ssam }
364