123369Smckusick /* 247540Skarels * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. 337728Smckusick * All rights reserved. 423369Smckusick * 544433Sbostic * %sccs.include.redist.c% 637728Smckusick * 7*59934Sakito * @(#)kern_exit.c 7.53 (Berkeley) 05/11/93 823369Smckusick */ 912790Ssam 1056517Sbostic #include <sys/param.h> 1156517Sbostic #include <sys/systm.h> 1256517Sbostic #include <sys/map.h> 1356517Sbostic #include <sys/ioctl.h> 1456517Sbostic #include <sys/proc.h> 1556517Sbostic #include <sys/tty.h> 1656517Sbostic #include <sys/time.h> 1756517Sbostic #include <sys/resource.h> 1856517Sbostic #include <sys/kernel.h> 1956517Sbostic #include <sys/buf.h> 2056517Sbostic #include <sys/wait.h> 2156517Sbostic #include <sys/file.h> 2256517Sbostic #include <sys/vnode.h> 2356517Sbostic #include <sys/syslog.h> 2456517Sbostic #include <sys/malloc.h> 2556517Sbostic #include <sys/resourcevar.h> 2656517Sbostic #include <sys/ptrace.h> 2712790Ssam 2856517Sbostic #include <machine/cpu.h> 2947540Skarels #ifdef COMPAT_43 3056517Sbostic #include <machine/reg.h> 3156517Sbostic #include <machine/psl.h> 3237328Skarels #endif 3337328Skarels 3456517Sbostic #include <vm/vm.h> 3556517Sbostic #include <vm/vm_kern.h> 3645739Smckusick 3712790Ssam /* 3812790Ssam * Exit system call: pass back caller's arg 3912790Ssam */ 4054921Storek struct rexit_args { 4154921Storek int rval; 4254921Storek }; 4342927Smckusick /* ARGSUSED */ 4442927Smckusick rexit(p, uap, retval) 4542927Smckusick struct proc *p; 4654921Storek struct rexit_args *uap; 4742927Smckusick int *retval; 4842927Smckusick { 4912790Ssam 5057864Sralph exit1(p, W_EXITCODE(uap->rval, 0)); 5145157Skarels /* NOTREACHED */ 5212790Ssam } 5312790Ssam 5412790Ssam /* 5547540Skarels * Exit: deallocate address space and other resources, 5647540Skarels * change proc state to zombie, and unlink proc from allproc 5747540Skarels * and parent's lists. Save exit status and rusage for wait(). 5847540Skarels * Check for child processes and orphan them. 5912790Ssam */ 6057864Sralph exit1(p, rv) 6147540Skarels register struct proc *p; 6238930Skarels int rv; 6312790Ssam { 6442927Smckusick register struct proc *q, *nq; 6540670Skarels register struct proc **pp; 6652491Smckusick register struct vmspace *vm; 6747540Skarels int s; 6812790Ssam 6954338Smckusick if (p->p_pid == 1) 7054338Smckusick panic("init died (signal %d, exit %d)", 7154338Smckusick WTERMSIG(rv), WEXITSTATUS(rv)); 7212790Ssam #ifdef PGINPROF 7312790Ssam vmsizmon(); 7412790Ssam #endif 7554133Smckusick if (p->p_flag & SPROFIL) 7654133Smckusick stopprofclock(p); 7732018Smckusick MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage), 7832018Smckusick M_ZOMBIE, M_WAITOK); 7947540Skarels /* 8047540Skarels * If parent is waiting for us to exit or exec, 8147540Skarels * SPPWAIT is set; we will wakeup the parent below. 8247540Skarels */ 8348403Skarels p->p_flag &= ~(STRC|SPPWAIT); 8412790Ssam p->p_flag |= SWEXIT; 8512882Ssam p->p_sigignore = ~0; 8639410Skarels p->p_sig = 0; 8712790Ssam untimeout(realitexpire, (caddr_t)p); 8847540Skarels 8947540Skarels /* 9047540Skarels * Close open files and release open-file table. 9147540Skarels * This may block! 9247540Skarels */ 9347540Skarels fdfree(p); 9450200Skarels 9550200Skarels /* The next two chunks should probably be moved to vmspace_exit. */ 9652491Smckusick vm = p->p_vmspace; 9745739Smckusick #ifdef SYSVSHM 9852491Smckusick if (vm->vm_shm) 9945739Smckusick shmexit(p); 10045739Smckusick #endif 10150200Skarels /* 10250200Skarels * Release user portion of address space. 10350200Skarels * This releases references to vnodes, 10450200Skarels * which could cause I/O if the file has been unlinked. 10550200Skarels * Need to do this early enough that we can still sleep. 10650200Skarels * Can't free the entire vmspace as the kernel stack 10750200Skarels * may be mapped within that space also. 10850200Skarels */ 10952491Smckusick if (vm->vm_refcnt == 1) 11052491Smckusick (void) vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS, 11150200Skarels VM_MAXUSER_ADDRESS); 11247540Skarels 11337328Skarels if (SESS_LEADER(p)) { 11442897Smarc register struct session *sp = p->p_session; 11542897Smarc 11642897Smarc if (sp->s_ttyvp) { 11740809Smarc /* 11842897Smarc * Controlling process. 11949087Skarels * Signal foreground pgrp, 12049087Skarels * drain controlling terminal 12149087Skarels * and revoke access to controlling terminal. 12242897Smarc */ 12349087Skarels if (sp->s_ttyp->t_session == sp) { 12449087Skarels if (sp->s_ttyp->t_pgrp) 12549087Skarels pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); 12649087Skarels (void) ttywait(sp->s_ttyp); 12749087Skarels vgoneall(sp->s_ttyvp); 12849087Skarels } 12942897Smarc vrele(sp->s_ttyvp); 13042897Smarc sp->s_ttyvp = NULL; 13142897Smarc /* 13240809Smarc * s_ttyp is not zero'd; we use this to indicate 13340809Smarc * that the session once had a controlling terminal. 13442897Smarc * (for logging and informational purposes) 13540809Smarc */ 13637328Skarels } 13749087Skarels sp->s_leader = NULL; 13837328Skarels } 13947540Skarels fixjobc(p, p->p_pgrp, 0); 14047540Skarels p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; 14143380Smckusick (void) acct(p); 14237328Skarels #ifdef KTRACE 14337328Skarels /* 14437328Skarels * release trace file 14537328Skarels */ 14652202Smarc p->p_traceflag = 0; /* don't trace the vrele() */ 14737328Skarels if (p->p_tracep) 14837728Smckusick vrele(p->p_tracep); 14937328Skarels #endif 15051014Skarels /* 15147540Skarels * Remove proc from allproc queue and pidhash chain. 15247540Skarels * Place onto zombproc. Unlink from parent's child list. 15347540Skarels */ 15447540Skarels if (*p->p_prev = p->p_nxt) 15516527Skarels p->p_nxt->p_prev = p->p_prev; 15647540Skarels if (p->p_nxt = zombproc) 15716527Skarels p->p_nxt->p_prev = &p->p_nxt; 15816527Skarels p->p_prev = &zombproc; 15916527Skarels zombproc = p; 16012790Ssam p->p_stat = SZOMB; 16152484Smckusick 16240670Skarels for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash) 16340670Skarels if (*pp == p) { 16440670Skarels *pp = p->p_hash; 16540670Skarels goto done; 16640670Skarels } 16740670Skarels panic("exit"); 16840670Skarels done: 16947540Skarels 17016527Skarels if (p->p_cptr) /* only need this if any child is S_ZOMB */ 17147540Skarels wakeup((caddr_t) initproc); 17216527Skarels for (q = p->p_cptr; q != NULL; q = nq) { 17316527Skarels nq = q->p_osptr; 17416527Skarels if (nq != NULL) 17516527Skarels nq->p_ysptr = NULL; 17647540Skarels if (initproc->p_cptr) 17747540Skarels initproc->p_cptr->p_ysptr = q; 17847540Skarels q->p_osptr = initproc->p_cptr; 17916527Skarels q->p_ysptr = NULL; 18047540Skarels initproc->p_cptr = q; 18112790Ssam 18247540Skarels q->p_pptr = initproc; 18316527Skarels /* 18416527Skarels * Traced processes are killed 18516527Skarels * since their existence means someone is screwing up. 18616527Skarels */ 18716527Skarels if (q->p_flag&STRC) { 18816527Skarels q->p_flag &= ~STRC; 18916527Skarels psignal(q, SIGKILL); 19012790Ssam } 19116527Skarels } 19217540Skarels p->p_cptr = NULL; 19347540Skarels 19447540Skarels /* 19554785Storek * Save exit status and final rusage info, adding in child rusage 19654816Storek * info and self times. 19747540Skarels */ 19847540Skarels p->p_xstat = rv; 19947540Skarels *p->p_ru = p->p_stats->p_ru; 20054785Storek calcru(p, &p->p_ru->ru_utime, &p->p_ru->ru_stime, NULL); 20147540Skarels ruadd(p->p_ru, &p->p_stats->p_cru); 20247540Skarels 20347540Skarels /* 20447540Skarels * Notify parent that we're gone. 20547540Skarels */ 20612790Ssam psignal(p->p_pptr, SIGCHLD); 20712790Ssam wakeup((caddr_t)p->p_pptr); 20829946Skarels #if defined(tahoe) 20949087Skarels /* move this to cpu_exit */ 21049087Skarels p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL; 21129946Skarels #endif 21247540Skarels /* 21352484Smckusick * Clear curproc after we've done all operations 21452484Smckusick * that could block, and before tearing down the rest 21552484Smckusick * of the process state that might be used from clock, etc. 21652484Smckusick * Also, can't clear curproc while we're still runnable, 21752484Smckusick * as we're not on a run queue (we are current, just not 21852484Smckusick * a proper proc any longer!). 21952484Smckusick * 22052484Smckusick * Other substructures are freed from wait(). 22152484Smckusick */ 22252484Smckusick curproc = NULL; 22352484Smckusick if (--p->p_limit->p_refcnt == 0) 22452484Smckusick FREE(p->p_limit, M_SUBPROC); 22552484Smckusick 22652484Smckusick /* 22749087Skarels * Finally, call machine-dependent code to release the remaining 22849087Skarels * resources including address space, the kernel stack and pcb. 22949087Skarels * The address space is released by "vmspace_free(p->p_vmspace)"; 23049087Skarels * This is machine-dependent, as we may have to change stacks 23149087Skarels * or ensure that the current one isn't reallocated before we 23254785Storek * finish. cpu_exit will end with a call to cpu_swtch(), finishing 23349087Skarels * our execution (pun intended). 23447540Skarels */ 23549087Skarels cpu_exit(p); 23647540Skarels /* NOTREACHED */ 23712790Ssam } 23812790Ssam 23954921Storek struct wait_args { 24054921Storek int pid; 24154921Storek int *status; 24254921Storek int options; 24354921Storek struct rusage *rusage; 24437328Skarels #ifdef COMPAT_43 24554921Storek int compat; /* pseudo */ 24654921Storek #endif 24754921Storek }; 24854921Storek 24954921Storek #ifdef COMPAT_43 250*59934Sakito #if defined(hp300) || defined(luna68k) 25157306Shibler #include <machine/frame.h> 25257306Shibler #define GETPS(rp) ((struct frame *)(rp))->f_sr 25357306Shibler #else 25457306Shibler #define GETPS(rp) (rp)[PS] 25557306Shibler #endif 25657306Shibler 25742927Smckusick owait(p, uap, retval) 25842927Smckusick struct proc *p; 25954921Storek register struct wait_args *uap; 26042927Smckusick int *retval; 26142927Smckusick { 26212790Ssam 26351015Sralph #ifdef PSL_ALLCC 26457306Shibler if ((GETPS(p->p_md.md_regs) & PSL_ALLCC) != PSL_ALLCC) { 26538930Skarels uap->options = 0; 26654921Storek uap->rusage = NULL; 26737328Skarels } else { 26852480Smckusick uap->options = p->p_md.md_regs[R0]; 26952480Smckusick uap->rusage = (struct rusage *)p->p_md.md_regs[R1]; 27012790Ssam } 27151015Sralph #else 27251015Sralph uap->options = 0; 27354921Storek uap->rusage = NULL; 27451015Sralph #endif 27537328Skarels uap->pid = WAIT_ANY; 27654921Storek uap->status = NULL; 27739410Skarels uap->compat = 1; 27844404Skarels return (wait1(p, uap, retval)); 27912790Ssam } 28012790Ssam 28142927Smckusick wait4(p, uap, retval) 28242927Smckusick struct proc *p; 28354921Storek struct wait_args *uap; 28442927Smckusick int *retval; 28542927Smckusick { 28639410Skarels 28739410Skarels uap->compat = 0; 28844404Skarels return (wait1(p, uap, retval)); 28937328Skarels } 29039410Skarels #else 29139410Skarels #define wait1 wait4 29237328Skarels #endif 29337328Skarels 29412790Ssam /* 29547540Skarels * Wait: check child processes to see if any have exited, 29647540Skarels * stopped under trace, or (optionally) stopped by a signal. 29747540Skarels * Pass back status and deallocate exited child's proc structure. 29812790Ssam */ 29942927Smckusick wait1(q, uap, retval) 30042927Smckusick register struct proc *q; 30154921Storek register struct wait_args *uap; 30242927Smckusick int retval[]; 30342927Smckusick { 30447540Skarels register int nfound; 30554338Smckusick register struct proc *p, *t; 30639410Skarels int status, error; 30712790Ssam 30837328Skarels if (uap->pid == 0) 30937328Skarels uap->pid = -q->p_pgid; 31038930Skarels #ifdef notyet 31139410Skarels if (uap->options &~ (WUNTRACED|WNOHANG)) 31244404Skarels return (EINVAL); 31338930Skarels #endif 31412790Ssam loop: 31547540Skarels nfound = 0; 31616527Skarels for (p = q->p_cptr; p; p = p->p_osptr) { 31737328Skarels if (uap->pid != WAIT_ANY && 31837328Skarels p->p_pid != uap->pid && p->p_pgid != -uap->pid) 31937328Skarels continue; 32047540Skarels nfound++; 32112790Ssam if (p->p_stat == SZOMB) { 32242927Smckusick retval[0] = p->p_pid; 32337328Skarels #ifdef COMPAT_43 32439410Skarels if (uap->compat) 32542927Smckusick retval[1] = p->p_xstat; 32637328Skarels else 32737328Skarels #endif 32837328Skarels if (uap->status) { 32939410Skarels status = p->p_xstat; /* convert to int */ 33039410Skarels if (error = copyout((caddr_t)&status, 33137328Skarels (caddr_t)uap->status, sizeof(status))) 33244404Skarels return (error); 33337328Skarels } 33439410Skarels if (uap->rusage && (error = copyout((caddr_t)p->p_ru, 33539410Skarels (caddr_t)uap->rusage, sizeof (struct rusage)))) 33644404Skarels return (error); 33754338Smckusick /* 33854338Smckusick * If we got the child via a ptrace 'attach', 33954338Smckusick * we need to give it back to the old parent. 34054338Smckusick */ 34154338Smckusick if (p->p_oppid && (t = pfind(p->p_oppid))) { 34254338Smckusick p->p_oppid = 0; 34354338Smckusick proc_reparent(p, t); 34454338Smckusick psignal(t, SIGCHLD); 34554338Smckusick wakeup((caddr_t)t); 34654338Smckusick return (0); 34754338Smckusick } 34812790Ssam p->p_xstat = 0; 34947540Skarels ruadd(&q->p_stats->p_cru, p->p_ru); 35037328Skarels FREE(p->p_ru, M_ZOMBIE); 35155405Smckusick 35255405Smckusick /* 35355405Smckusick * Decrement the count of procs running with this uid. 35455405Smckusick */ 35555405Smckusick (void)chgproccnt(p->p_cred->p_ruid, -1); 35655405Smckusick 35755405Smckusick /* 35855405Smckusick * Free up credentials. 35955405Smckusick */ 36050200Skarels if (--p->p_cred->p_refcnt == 0) { 36150200Skarels crfree(p->p_cred->pc_ucred); 36250200Skarels FREE(p->p_cred, M_SUBPROC); 36350200Skarels } 36447540Skarels 36547540Skarels /* 36647540Skarels * Finally finished with old proc entry. 36747540Skarels * Unlink it from its process group and free it. 36847540Skarels */ 36947540Skarels leavepgrp(p); 37016527Skarels if (*p->p_prev = p->p_nxt) /* off zombproc */ 37116527Skarels p->p_nxt->p_prev = p->p_prev; 37212790Ssam if (q = p->p_ysptr) 37312790Ssam q->p_osptr = p->p_osptr; 37412790Ssam if (q = p->p_osptr) 37512790Ssam q->p_ysptr = p->p_ysptr; 37612790Ssam if ((q = p->p_pptr)->p_cptr == p) 37712790Ssam q->p_cptr = p->p_osptr; 37849690Swilliam 37950200Skarels /* 38050200Skarels * Give machine-dependent layer a chance 38150200Skarels * to free anything that cpu_exit couldn't 38250200Skarels * release while still running in process context. 38350200Skarels */ 38450200Skarels cpu_wait(p); 38547540Skarels FREE(p, M_PROC); 38647540Skarels nprocs--; 38744404Skarels return (0); 38812790Ssam } 38937328Skarels if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 && 39037328Skarels (p->p_flag & STRC || uap->options & WUNTRACED)) { 39112790Ssam p->p_flag |= SWTED; 39242927Smckusick retval[0] = p->p_pid; 39337328Skarels #ifdef COMPAT_43 39439737Smckusick if (uap->compat) { 39543895Skarels retval[1] = W_STOPCODE(p->p_xstat); 39639737Smckusick error = 0; 39739737Smckusick } else 39837328Skarels #endif 39937328Skarels if (uap->status) { 40043895Skarels status = W_STOPCODE(p->p_xstat); 40139410Skarels error = copyout((caddr_t)&status, 40251015Sralph (caddr_t)uap->status, sizeof(status)); 40339410Skarels } else 40439410Skarels error = 0; 40544404Skarels return (error); 40612790Ssam } 40712790Ssam } 40847540Skarels if (nfound == 0) 40944404Skarels return (ECHILD); 41037328Skarels if (uap->options & WNOHANG) { 41142927Smckusick retval[0] = 0; 41244404Skarels return (0); 41312790Ssam } 41442927Smckusick if (error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0)) 41544404Skarels return (error); 41612790Ssam goto loop; 41712790Ssam } 41854338Smckusick 41954338Smckusick /* 42054338Smckusick * make process 'parent' the new parent of process 'child'. 42154338Smckusick */ 42254338Smckusick void 42354338Smckusick proc_reparent(child, parent) 42454338Smckusick register struct proc *child; 42554338Smckusick register struct proc *parent; 42654338Smckusick { 42754338Smckusick register struct proc *o; 42854338Smckusick register struct proc *y; 42954338Smckusick 43054338Smckusick if (child->p_pptr == parent) 43154338Smckusick return; 43254338Smckusick 43354338Smckusick /* fix up the child linkage for the old parent */ 43454338Smckusick o = child->p_osptr; 43554338Smckusick y = child->p_ysptr; 43654338Smckusick if (y) 43754338Smckusick y->p_osptr = o; 43854338Smckusick if (o) 43954338Smckusick o->p_ysptr = y; 44054338Smckusick if (child->p_pptr->p_cptr == child) 44154338Smckusick child->p_pptr->p_cptr = o; 44254338Smckusick 44354338Smckusick /* fix up child linkage for new parent */ 44454338Smckusick o = parent->p_cptr; 44554338Smckusick if (o) 44654338Smckusick o->p_ysptr = child; 44754338Smckusick child->p_osptr = o; 44854338Smckusick child->p_ysptr = NULL; 44954338Smckusick parent->p_cptr = child; 45054338Smckusick child->p_pptr = parent; 45154338Smckusick } 452