123369Smckusick /* 2*47540Skarels * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. 337728Smckusick * All rights reserved. 423369Smckusick * 544433Sbostic * %sccs.include.redist.c% 637728Smckusick * 7*47540Skarels * @(#)kern_exit.c 7.31 (Berkeley) 03/17/91 823369Smckusick */ 912790Ssam 1017090Sbloom #include "param.h" 1117090Sbloom #include "systm.h" 1217090Sbloom #include "map.h" 1342927Smckusick #include "ioctl.h" 1442927Smckusick #include "tty.h" 15*47540Skarels #include "time.h" 16*47540Skarels #include "resource.h" 1744404Skarels #include "user.h" 1817090Sbloom #include "kernel.h" 1917090Sbloom #include "proc.h" 2017090Sbloom #include "buf.h" 2117090Sbloom #include "wait.h" 2217090Sbloom #include "file.h" 2337728Smckusick #include "vnode.h" 2418638Ssam #include "syslog.h" 2532018Smckusick #include "malloc.h" 2612790Ssam 27*47540Skarels #ifdef COMPAT_43 2837520Smckusick #include "machine/reg.h" 2937520Smckusick #include "machine/psl.h" 3037328Skarels #endif 3137328Skarels 32*47540Skarels #include "vm/vm_param.h" 33*47540Skarels #include "vm/vm_map.h" 34*47540Skarels #include "vm/vm_kern.h" 3545739Smckusick 3612790Ssam /* 3712790Ssam * Exit system call: pass back caller's arg 3812790Ssam */ 3942927Smckusick /* ARGSUSED */ 4042927Smckusick rexit(p, uap, retval) 4142927Smckusick struct proc *p; 4242927Smckusick struct args { 4312790Ssam int rval; 4412790Ssam } *uap; 4542927Smckusick int *retval; 4642927Smckusick { 4712790Ssam 4845157Skarels exit(p, W_EXITCODE(uap->rval, 0)); 4945157Skarels /* NOTREACHED */ 5012790Ssam } 5112790Ssam 5212790Ssam /* 53*47540Skarels * Exit: deallocate address space and other resources, 54*47540Skarels * change proc state to zombie, and unlink proc from allproc 55*47540Skarels * and parent's lists. Save exit status and rusage for wait(). 56*47540Skarels * Check for child processes and orphan them. 5712790Ssam */ 5842927Smckusick exit(p, rv) 59*47540Skarels register struct proc *p; 6038930Skarels int rv; 6112790Ssam { 6242927Smckusick register struct proc *q, *nq; 6340670Skarels register struct proc **pp; 64*47540Skarels int s; 6512790Ssam 6612790Ssam #ifdef PGINPROF 6712790Ssam vmsizmon(); 6812790Ssam #endif 6932018Smckusick MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage), 7032018Smckusick M_ZOMBIE, M_WAITOK); 71*47540Skarels /* 72*47540Skarels * If parent is waiting for us to exit or exec, 73*47540Skarels * SPPWAIT is set; we will wakeup the parent below. 74*47540Skarels */ 75*47540Skarels p->p_flag &= ~(STRC|SULOCK|SPPWAIT); 7612790Ssam p->p_flag |= SWEXIT; 7712882Ssam p->p_sigignore = ~0; 7839410Skarels p->p_sig = 0; 7912790Ssam untimeout(realitexpire, (caddr_t)p); 80*47540Skarels 81*47540Skarels /* 82*47540Skarels * Close open files and release open-file table. 83*47540Skarels * This may block! 84*47540Skarels */ 85*47540Skarels fdfree(p); 86*47540Skarels p->p_fd = 0; 8745739Smckusick #ifdef SYSVSHM 88*47540Skarels if (p->p_vmspace->vm_shm) 8945739Smckusick shmexit(p); 9045739Smckusick #endif 91*47540Skarels vmspace_free(p->p_vmspace); 92*47540Skarels p->p_vmspace = 0; 93*47540Skarels 94*47540Skarels if (p->p_pid == 1) 95*47540Skarels panic("init died"); 9637328Skarels if (SESS_LEADER(p)) { 9742897Smarc register struct session *sp = p->p_session; 9842897Smarc 9942897Smarc if (sp->s_ttyvp) { 10040809Smarc /* 10142897Smarc * Controlling process. 10242897Smarc * Signal foreground pgrp and revoke access 10342897Smarc * to controlling terminal. 10442897Smarc */ 10542897Smarc if (sp->s_ttyp->t_pgrp) 10642916Smarc pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); 10742897Smarc vgoneall(sp->s_ttyvp); 10842897Smarc vrele(sp->s_ttyvp); 10942897Smarc sp->s_ttyvp = NULL; 11042897Smarc /* 11140809Smarc * s_ttyp is not zero'd; we use this to indicate 11240809Smarc * that the session once had a controlling terminal. 11342897Smarc * (for logging and informational purposes) 11440809Smarc */ 11537328Skarels } 11642897Smarc sp->s_leader = 0; 11737328Skarels } 118*47540Skarels fixjobc(p, p->p_pgrp, 0); 119*47540Skarels p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; 12043380Smckusick (void) acct(p); 121*47540Skarels if (--p->p_limit->p_refcnt == 0) 122*47540Skarels FREE(p->p_limit, M_SUBPROC); 123*47540Skarels if (--p->p_cred->p_refcnt == 0) { 124*47540Skarels crfree(p->p_cred->pc_ucred); 125*47540Skarels FREE(p->p_cred, M_SUBPROC); 126*47540Skarels } 12737328Skarels #ifdef KTRACE 12837328Skarels /* 12937328Skarels * release trace file 13037328Skarels */ 13137328Skarels if (p->p_tracep) 13237728Smckusick vrele(p->p_tracep); 13337328Skarels #endif 134*47540Skarels 135*47540Skarels /* 136*47540Skarels * Remove proc from allproc queue and pidhash chain. 137*47540Skarels * Place onto zombproc. Unlink from parent's child list. 138*47540Skarels */ 139*47540Skarels if (*p->p_prev = p->p_nxt) 14016527Skarels p->p_nxt->p_prev = p->p_prev; 141*47540Skarels if (p->p_nxt = zombproc) 14216527Skarels p->p_nxt->p_prev = &p->p_nxt; 14316527Skarels p->p_prev = &zombproc; 14416527Skarels zombproc = p; 14512790Ssam p->p_stat = SZOMB; 14612790Ssam noproc = 1; 14740670Skarels for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash) 14840670Skarels if (*pp == p) { 14940670Skarels *pp = p->p_hash; 15040670Skarels goto done; 15140670Skarels } 15240670Skarels panic("exit"); 15340670Skarels done: 154*47540Skarels 15516527Skarels if (p->p_cptr) /* only need this if any child is S_ZOMB */ 156*47540Skarels wakeup((caddr_t) initproc); 15716527Skarels for (q = p->p_cptr; q != NULL; q = nq) { 15816527Skarels nq = q->p_osptr; 15916527Skarels if (nq != NULL) 16016527Skarels nq->p_ysptr = NULL; 161*47540Skarels if (initproc->p_cptr) 162*47540Skarels initproc->p_cptr->p_ysptr = q; 163*47540Skarels q->p_osptr = initproc->p_cptr; 16416527Skarels q->p_ysptr = NULL; 165*47540Skarels initproc->p_cptr = q; 16612790Ssam 167*47540Skarels q->p_pptr = initproc; 16816527Skarels /* 16916527Skarels * Traced processes are killed 17016527Skarels * since their existence means someone is screwing up. 17116527Skarels */ 17216527Skarels if (q->p_flag&STRC) { 17316527Skarels q->p_flag &= ~STRC; 17416527Skarels psignal(q, SIGKILL); 17512790Ssam } 17616527Skarels } 17717540Skarels p->p_cptr = NULL; 178*47540Skarels 179*47540Skarels /* 180*47540Skarels * Save exit status and final rusage info, 181*47540Skarels * adding in child rusage info and self times. 182*47540Skarels */ 183*47540Skarels p->p_xstat = rv; 184*47540Skarels *p->p_ru = p->p_stats->p_ru; 185*47540Skarels p->p_ru->ru_stime = p->p_stime; 186*47540Skarels p->p_ru->ru_utime = p->p_utime; 187*47540Skarels ruadd(p->p_ru, &p->p_stats->p_cru); 188*47540Skarels 189*47540Skarels /* 190*47540Skarels * Notify parent that we're gone. 191*47540Skarels */ 19212790Ssam psignal(p->p_pptr, SIGCHLD); 19312790Ssam wakeup((caddr_t)p->p_pptr); 19429946Skarels #if defined(tahoe) 19529946Skarels u.u_pcb.pcb_savacc.faddr = (float *)NULL; 19629946Skarels #endif 197*47540Skarels /* 198*47540Skarels * Free the memory for the user structure and kernel stack. 199*47540Skarels * As we continue using it until the swtch completes 200*47540Skarels * (or switches to an interrupt stack), we need to block 201*47540Skarels * memory allocation by raising priority until we are gone. 202*47540Skarels */ 203*47540Skarels (void) splimp(); 204*47540Skarels /* I don't think this will cause a sleep/realloc anywhere... */ 205*47540Skarels kmem_free(kernel_map, (vm_offset_t)p->p_addr, 206*47540Skarels round_page(ctob(UPAGES))); 20712790Ssam swtch(); 208*47540Skarels /* NOTREACHED */ 20912790Ssam } 21012790Ssam 21137328Skarels #ifdef COMPAT_43 21242927Smckusick owait(p, uap, retval) 21342927Smckusick struct proc *p; 21442927Smckusick register struct args { 21537328Skarels int pid; 21639410Skarels int *status; 21737328Skarels int options; 21837328Skarels struct rusage *rusage; 21939410Skarels int compat; 22042927Smckusick } *uap; 22142927Smckusick int *retval; 22242927Smckusick { 22312790Ssam 224*47540Skarels if ((p->p_regs[PS] & PSL_ALLCC) != PSL_ALLCC) { 22538930Skarels uap->options = 0; 22637328Skarels uap->rusage = 0; 22737328Skarels } else { 228*47540Skarels uap->options = p->p_regs[R0]; 229*47540Skarels uap->rusage = (struct rusage *)p->p_regs[R1]; 23012790Ssam } 23137328Skarels uap->pid = WAIT_ANY; 23237328Skarels uap->status = 0; 23339410Skarels uap->compat = 1; 23444404Skarels return (wait1(p, uap, retval)); 23512790Ssam } 23612790Ssam 23742927Smckusick wait4(p, uap, retval) 23842927Smckusick struct proc *p; 23942927Smckusick struct args { 24039410Skarels int pid; 24139410Skarels int *status; 24239410Skarels int options; 24339410Skarels struct rusage *rusage; 24439410Skarels int compat; 24542927Smckusick } *uap; 24642927Smckusick int *retval; 24742927Smckusick { 24839410Skarels 24939410Skarels uap->compat = 0; 25044404Skarels return (wait1(p, uap, retval)); 25137328Skarels } 25239410Skarels #else 25339410Skarels #define wait1 wait4 25437328Skarels #endif 25537328Skarels 25612790Ssam /* 257*47540Skarels * Wait: check child processes to see if any have exited, 258*47540Skarels * stopped under trace, or (optionally) stopped by a signal. 259*47540Skarels * Pass back status and deallocate exited child's proc structure. 26012790Ssam */ 26142927Smckusick wait1(q, uap, retval) 26242927Smckusick register struct proc *q; 26342927Smckusick register struct args { 26437328Skarels int pid; 26539410Skarels int *status; 26637328Skarels int options; 26737328Skarels struct rusage *rusage; 26839410Skarels #ifdef COMPAT_43 26939410Skarels int compat; 27039410Skarels #endif 27142927Smckusick } *uap; 27242927Smckusick int retval[]; 27342927Smckusick { 274*47540Skarels register int nfound; 27542927Smckusick register struct proc *p; 27639410Skarels int status, error; 27712790Ssam 27837328Skarels if (uap->pid == 0) 27937328Skarels uap->pid = -q->p_pgid; 28038930Skarels #ifdef notyet 28139410Skarels if (uap->options &~ (WUNTRACED|WNOHANG)) 28244404Skarels return (EINVAL); 28338930Skarels #endif 28412790Ssam loop: 285*47540Skarels nfound = 0; 28616527Skarels for (p = q->p_cptr; p; p = p->p_osptr) { 28737328Skarels if (uap->pid != WAIT_ANY && 28837328Skarels p->p_pid != uap->pid && p->p_pgid != -uap->pid) 28937328Skarels continue; 290*47540Skarels nfound++; 29112790Ssam if (p->p_stat == SZOMB) { 29242927Smckusick retval[0] = p->p_pid; 29337328Skarels #ifdef COMPAT_43 29439410Skarels if (uap->compat) 29542927Smckusick retval[1] = p->p_xstat; 29637328Skarels else 29737328Skarels #endif 29837328Skarels if (uap->status) { 29939410Skarels status = p->p_xstat; /* convert to int */ 30039410Skarels if (error = copyout((caddr_t)&status, 30137328Skarels (caddr_t)uap->status, sizeof(status))) 30244404Skarels return (error); 30337328Skarels } 30439410Skarels if (uap->rusage && (error = copyout((caddr_t)p->p_ru, 30539410Skarels (caddr_t)uap->rusage, sizeof (struct rusage)))) 30644404Skarels return (error); 30712790Ssam p->p_xstat = 0; 308*47540Skarels ruadd(&q->p_stats->p_cru, p->p_ru); 30937328Skarels FREE(p->p_ru, M_ZOMBIE); 310*47540Skarels 311*47540Skarels /* 312*47540Skarels * Finally finished with old proc entry. 313*47540Skarels * Unlink it from its process group and free it. 314*47540Skarels */ 315*47540Skarels leavepgrp(p); 31616527Skarels if (*p->p_prev = p->p_nxt) /* off zombproc */ 31716527Skarels p->p_nxt->p_prev = p->p_prev; 31812790Ssam if (q = p->p_ysptr) 31912790Ssam q->p_osptr = p->p_osptr; 32012790Ssam if (q = p->p_osptr) 32112790Ssam q->p_ysptr = p->p_ysptr; 32212790Ssam if ((q = p->p_pptr)->p_cptr == p) 32312790Ssam q->p_cptr = p->p_osptr; 324*47540Skarels FREE(p, M_PROC); 325*47540Skarels nprocs--; 32644404Skarels return (0); 32712790Ssam } 32837328Skarels if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 && 32937328Skarels (p->p_flag & STRC || uap->options & WUNTRACED)) { 33012790Ssam p->p_flag |= SWTED; 33142927Smckusick retval[0] = p->p_pid; 33237328Skarels #ifdef COMPAT_43 33339737Smckusick if (uap->compat) { 33443895Skarels retval[1] = W_STOPCODE(p->p_xstat); 33539737Smckusick error = 0; 33639737Smckusick } else 33737328Skarels #endif 33837328Skarels if (uap->status) { 33943895Skarels status = W_STOPCODE(p->p_xstat); 34039410Skarels error = copyout((caddr_t)&status, 34137328Skarels (caddr_t)uap->status, sizeof(status)); 34239410Skarels } else 34339410Skarels error = 0; 34444404Skarels return (error); 34512790Ssam } 34612790Ssam } 347*47540Skarels if (nfound == 0) 34844404Skarels return (ECHILD); 34937328Skarels if (uap->options & WNOHANG) { 35042927Smckusick retval[0] = 0; 35144404Skarels return (0); 35212790Ssam } 35342927Smckusick if (error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0)) 35444404Skarels return (error); 35512790Ssam goto loop; 35612790Ssam } 357