123369Smckusick /* 263442Sbostic * Copyright (c) 1982, 1986, 1989, 1991, 1993 363442Sbostic * The Regents of the University of California. All rights reserved. 465771Sbostic * (c) UNIX System Laboratories, Inc. 565771Sbostic * All or some portions of this file are derived from material licensed 665771Sbostic * to the University of California by American Telephone and Telegraph 765771Sbostic * Co. or Unix System Laboratories, Inc. and are reproduced herein with 865771Sbostic * the permission of UNIX System Laboratories, Inc. 923369Smckusick * 1044433Sbostic * %sccs.include.redist.c% 1137728Smckusick * 12*66071Skarels * @(#)kern_exit.c 8.7 (Berkeley) 02/12/94 1323369Smckusick */ 1412790Ssam 1556517Sbostic #include <sys/param.h> 1656517Sbostic #include <sys/systm.h> 1756517Sbostic #include <sys/map.h> 1856517Sbostic #include <sys/ioctl.h> 1956517Sbostic #include <sys/proc.h> 2056517Sbostic #include <sys/tty.h> 2156517Sbostic #include <sys/time.h> 2256517Sbostic #include <sys/resource.h> 2356517Sbostic #include <sys/kernel.h> 2456517Sbostic #include <sys/buf.h> 2556517Sbostic #include <sys/wait.h> 2656517Sbostic #include <sys/file.h> 2756517Sbostic #include <sys/vnode.h> 2856517Sbostic #include <sys/syslog.h> 2956517Sbostic #include <sys/malloc.h> 3056517Sbostic #include <sys/resourcevar.h> 3156517Sbostic #include <sys/ptrace.h> 3212790Ssam 3356517Sbostic #include <machine/cpu.h> 3447540Skarels #ifdef COMPAT_43 3556517Sbostic #include <machine/reg.h> 3656517Sbostic #include <machine/psl.h> 3737328Skarels #endif 3837328Skarels 3956517Sbostic #include <vm/vm.h> 4056517Sbostic #include <vm/vm_kern.h> 4145739Smckusick 4263441Sbostic __dead void cpu_exit __P((struct proc *)); 4363441Sbostic __dead void exit1 __P((struct proc *, int)); 4463441Sbostic 4512790Ssam /* 4663426Sbostic * exit -- 4763426Sbostic * Death of process. 4812790Ssam */ 4954921Storek struct rexit_args { 5054921Storek int rval; 5154921Storek }; 5263441Sbostic __dead void 5363426Sbostic exit(p, uap, retval) 5442927Smckusick struct proc *p; 5554921Storek struct rexit_args *uap; 5642927Smckusick int *retval; 5742927Smckusick { 5812790Ssam 5957864Sralph exit1(p, W_EXITCODE(uap->rval, 0)); 6045157Skarels /* NOTREACHED */ 6112790Ssam } 6212790Ssam 6312790Ssam /* 6463426Sbostic * Exit: deallocate address space and other resources, change proc state 6563426Sbostic * to zombie, and unlink proc from allproc and parent's lists. Save exit 6663426Sbostic * status and rusage for wait(). Check for child processes and orphan them. 6712790Ssam */ 6863441Sbostic __dead void 6957864Sralph exit1(p, rv) 7047540Skarels register struct proc *p; 7138930Skarels int rv; 7212790Ssam { 7342927Smckusick register struct proc *q, *nq; 7440670Skarels register struct proc **pp; 7552491Smckusick register struct vmspace *vm; 7612790Ssam 7754338Smckusick if (p->p_pid == 1) 7854338Smckusick panic("init died (signal %d, exit %d)", 7954338Smckusick WTERMSIG(rv), WEXITSTATUS(rv)); 8012790Ssam #ifdef PGINPROF 8112790Ssam vmsizmon(); 8212790Ssam #endif 8364582Sbostic if (p->p_flag & P_PROFIL) 8454133Smckusick stopprofclock(p); 8532018Smckusick MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage), 8632018Smckusick M_ZOMBIE, M_WAITOK); 8747540Skarels /* 8847540Skarels * If parent is waiting for us to exit or exec, 8964582Sbostic * P_PPWAIT is set; we will wakeup the parent below. 9047540Skarels */ 9164582Sbostic p->p_flag &= ~(P_TRACED | P_PPWAIT); 9264582Sbostic p->p_flag |= P_WEXIT; 9312882Ssam p->p_sigignore = ~0; 9464582Sbostic p->p_siglist = 0; 9512790Ssam untimeout(realitexpire, (caddr_t)p); 9647540Skarels 9747540Skarels /* 9847540Skarels * Close open files and release open-file table. 9947540Skarels * This may block! 10047540Skarels */ 10147540Skarels fdfree(p); 10250200Skarels 10350200Skarels /* The next two chunks should probably be moved to vmspace_exit. */ 10452491Smckusick vm = p->p_vmspace; 10545739Smckusick #ifdef SYSVSHM 10652491Smckusick if (vm->vm_shm) 10745739Smckusick shmexit(p); 10845739Smckusick #endif 10950200Skarels /* 11050200Skarels * Release user portion of address space. 11150200Skarels * This releases references to vnodes, 11250200Skarels * which could cause I/O if the file has been unlinked. 11350200Skarels * Need to do this early enough that we can still sleep. 11450200Skarels * Can't free the entire vmspace as the kernel stack 11550200Skarels * may be mapped within that space also. 11650200Skarels */ 11752491Smckusick if (vm->vm_refcnt == 1) 11852491Smckusick (void) vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS, 11950200Skarels VM_MAXUSER_ADDRESS); 12047540Skarels 12137328Skarels if (SESS_LEADER(p)) { 12242897Smarc register struct session *sp = p->p_session; 12342897Smarc 12442897Smarc if (sp->s_ttyvp) { 12540809Smarc /* 12642897Smarc * Controlling process. 12749087Skarels * Signal foreground pgrp, 12849087Skarels * drain controlling terminal 12949087Skarels * and revoke access to controlling terminal. 13042897Smarc */ 13149087Skarels if (sp->s_ttyp->t_session == sp) { 13249087Skarels if (sp->s_ttyp->t_pgrp) 13349087Skarels pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); 13449087Skarels (void) ttywait(sp->s_ttyp); 135*66071Skarels /* 136*66071Skarels * The tty could have been revoked 137*66071Skarels * if we blocked. 138*66071Skarels */ 139*66071Skarels if (sp->s_ttyvp) 140*66071Skarels vgoneall(sp->s_ttyvp); 14149087Skarels } 142*66071Skarels if (sp->s_ttyvp) 143*66071Skarels vrele(sp->s_ttyvp); 14442897Smarc sp->s_ttyvp = NULL; 14542897Smarc /* 14640809Smarc * s_ttyp is not zero'd; we use this to indicate 14740809Smarc * that the session once had a controlling terminal. 14842897Smarc * (for logging and informational purposes) 14940809Smarc */ 15037328Skarels } 15149087Skarels sp->s_leader = NULL; 15237328Skarels } 15347540Skarels fixjobc(p, p->p_pgrp, 0); 15447540Skarels p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; 15563430Sbostic (void)acct_process(p); 15637328Skarels #ifdef KTRACE 15737328Skarels /* 15837328Skarels * release trace file 15937328Skarels */ 16052202Smarc p->p_traceflag = 0; /* don't trace the vrele() */ 16137328Skarels if (p->p_tracep) 16237728Smckusick vrele(p->p_tracep); 16337328Skarels #endif 16451014Skarels /* 16547540Skarels * Remove proc from allproc queue and pidhash chain. 16647540Skarels * Place onto zombproc. Unlink from parent's child list. 16747540Skarels */ 16864582Sbostic if (*p->p_prev = p->p_next) 16964582Sbostic p->p_next->p_prev = p->p_prev; 17064582Sbostic if (p->p_next = zombproc) 17164582Sbostic p->p_next->p_prev = &p->p_next; 17216527Skarels p->p_prev = &zombproc; 17316527Skarels zombproc = p; 17412790Ssam p->p_stat = SZOMB; 17552484Smckusick 17640670Skarels for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash) 17740670Skarels if (*pp == p) { 17840670Skarels *pp = p->p_hash; 17940670Skarels goto done; 18040670Skarels } 18140670Skarels panic("exit"); 18240670Skarels done: 18347540Skarels 18416527Skarels if (p->p_cptr) /* only need this if any child is S_ZOMB */ 18547540Skarels wakeup((caddr_t) initproc); 18616527Skarels for (q = p->p_cptr; q != NULL; q = nq) { 18716527Skarels nq = q->p_osptr; 18816527Skarels if (nq != NULL) 18916527Skarels nq->p_ysptr = NULL; 19047540Skarels if (initproc->p_cptr) 19147540Skarels initproc->p_cptr->p_ysptr = q; 19247540Skarels q->p_osptr = initproc->p_cptr; 19316527Skarels q->p_ysptr = NULL; 19447540Skarels initproc->p_cptr = q; 19512790Ssam 19647540Skarels q->p_pptr = initproc; 19716527Skarels /* 19816527Skarels * Traced processes are killed 19916527Skarels * since their existence means someone is screwing up. 20016527Skarels */ 20164582Sbostic if (q->p_flag & P_TRACED) { 20264582Sbostic q->p_flag &= ~P_TRACED; 20316527Skarels psignal(q, SIGKILL); 20412790Ssam } 20516527Skarels } 20617540Skarels p->p_cptr = NULL; 20747540Skarels 20847540Skarels /* 20954785Storek * Save exit status and final rusage info, adding in child rusage 21054816Storek * info and self times. 21147540Skarels */ 21247540Skarels p->p_xstat = rv; 21347540Skarels *p->p_ru = p->p_stats->p_ru; 21454785Storek calcru(p, &p->p_ru->ru_utime, &p->p_ru->ru_stime, NULL); 21547540Skarels ruadd(p->p_ru, &p->p_stats->p_cru); 21647540Skarels 21747540Skarels /* 21847540Skarels * Notify parent that we're gone. 21947540Skarels */ 22012790Ssam psignal(p->p_pptr, SIGCHLD); 22112790Ssam wakeup((caddr_t)p->p_pptr); 22229946Skarels #if defined(tahoe) 22349087Skarels /* move this to cpu_exit */ 22449087Skarels p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL; 22529946Skarels #endif 22647540Skarels /* 22752484Smckusick * Clear curproc after we've done all operations 22852484Smckusick * that could block, and before tearing down the rest 22952484Smckusick * of the process state that might be used from clock, etc. 23052484Smckusick * Also, can't clear curproc while we're still runnable, 23152484Smckusick * as we're not on a run queue (we are current, just not 23252484Smckusick * a proper proc any longer!). 23352484Smckusick * 23452484Smckusick * Other substructures are freed from wait(). 23552484Smckusick */ 23652484Smckusick curproc = NULL; 23752484Smckusick if (--p->p_limit->p_refcnt == 0) 23852484Smckusick FREE(p->p_limit, M_SUBPROC); 23952484Smckusick 24052484Smckusick /* 24149087Skarels * Finally, call machine-dependent code to release the remaining 24249087Skarels * resources including address space, the kernel stack and pcb. 24349087Skarels * The address space is released by "vmspace_free(p->p_vmspace)"; 24449087Skarels * This is machine-dependent, as we may have to change stacks 24549087Skarels * or ensure that the current one isn't reallocated before we 24654785Storek * finish. cpu_exit will end with a call to cpu_swtch(), finishing 24749087Skarels * our execution (pun intended). 24847540Skarels */ 24949087Skarels cpu_exit(p); 25012790Ssam } 25112790Ssam 25254921Storek struct wait_args { 25354921Storek int pid; 25454921Storek int *status; 25554921Storek int options; 25654921Storek struct rusage *rusage; 25737328Skarels #ifdef COMPAT_43 25854921Storek int compat; /* pseudo */ 25954921Storek #endif 26054921Storek }; 26154921Storek 26254921Storek #ifdef COMPAT_43 26359934Sakito #if defined(hp300) || defined(luna68k) 26457306Shibler #include <machine/frame.h> 26557306Shibler #define GETPS(rp) ((struct frame *)(rp))->f_sr 26657306Shibler #else 26757306Shibler #define GETPS(rp) (rp)[PS] 26857306Shibler #endif 26957306Shibler 27042927Smckusick owait(p, uap, retval) 27142927Smckusick struct proc *p; 27254921Storek register struct wait_args *uap; 27342927Smckusick int *retval; 27442927Smckusick { 27512790Ssam 27651015Sralph #ifdef PSL_ALLCC 27757306Shibler if ((GETPS(p->p_md.md_regs) & PSL_ALLCC) != PSL_ALLCC) { 27838930Skarels uap->options = 0; 27954921Storek uap->rusage = NULL; 28037328Skarels } else { 28152480Smckusick uap->options = p->p_md.md_regs[R0]; 28252480Smckusick uap->rusage = (struct rusage *)p->p_md.md_regs[R1]; 28312790Ssam } 28451015Sralph #else 28551015Sralph uap->options = 0; 28654921Storek uap->rusage = NULL; 28751015Sralph #endif 28837328Skarels uap->pid = WAIT_ANY; 28954921Storek uap->status = NULL; 29039410Skarels uap->compat = 1; 29144404Skarels return (wait1(p, uap, retval)); 29212790Ssam } 29312790Ssam 29442927Smckusick wait4(p, uap, retval) 29542927Smckusick struct proc *p; 29654921Storek struct wait_args *uap; 29742927Smckusick int *retval; 29842927Smckusick { 29939410Skarels 30039410Skarels uap->compat = 0; 30144404Skarels return (wait1(p, uap, retval)); 30237328Skarels } 30339410Skarels #else 30439410Skarels #define wait1 wait4 30537328Skarels #endif 30637328Skarels 30764537Sbostic int 30842927Smckusick wait1(q, uap, retval) 30942927Smckusick register struct proc *q; 31054921Storek register struct wait_args *uap; 31142927Smckusick int retval[]; 31242927Smckusick { 31347540Skarels register int nfound; 31454338Smckusick register struct proc *p, *t; 31539410Skarels int status, error; 31612790Ssam 31737328Skarels if (uap->pid == 0) 31837328Skarels uap->pid = -q->p_pgid; 31938930Skarels #ifdef notyet 32039410Skarels if (uap->options &~ (WUNTRACED|WNOHANG)) 32144404Skarels return (EINVAL); 32238930Skarels #endif 32312790Ssam loop: 32447540Skarels nfound = 0; 32516527Skarels for (p = q->p_cptr; p; p = p->p_osptr) { 32637328Skarels if (uap->pid != WAIT_ANY && 32737328Skarels p->p_pid != uap->pid && p->p_pgid != -uap->pid) 32837328Skarels continue; 32947540Skarels nfound++; 33012790Ssam if (p->p_stat == SZOMB) { 33142927Smckusick retval[0] = p->p_pid; 33237328Skarels #ifdef COMPAT_43 33339410Skarels if (uap->compat) 33442927Smckusick retval[1] = p->p_xstat; 33537328Skarels else 33637328Skarels #endif 33737328Skarels if (uap->status) { 33839410Skarels status = p->p_xstat; /* convert to int */ 33939410Skarels if (error = copyout((caddr_t)&status, 34037328Skarels (caddr_t)uap->status, sizeof(status))) 34144404Skarels return (error); 34237328Skarels } 34339410Skarels if (uap->rusage && (error = copyout((caddr_t)p->p_ru, 34439410Skarels (caddr_t)uap->rusage, sizeof (struct rusage)))) 34544404Skarels return (error); 34654338Smckusick /* 34754338Smckusick * If we got the child via a ptrace 'attach', 34854338Smckusick * we need to give it back to the old parent. 34954338Smckusick */ 35054338Smckusick if (p->p_oppid && (t = pfind(p->p_oppid))) { 35154338Smckusick p->p_oppid = 0; 35254338Smckusick proc_reparent(p, t); 35354338Smckusick psignal(t, SIGCHLD); 35454338Smckusick wakeup((caddr_t)t); 35554338Smckusick return (0); 35654338Smckusick } 35712790Ssam p->p_xstat = 0; 35847540Skarels ruadd(&q->p_stats->p_cru, p->p_ru); 35937328Skarels FREE(p->p_ru, M_ZOMBIE); 36055405Smckusick 36155405Smckusick /* 36255405Smckusick * Decrement the count of procs running with this uid. 36355405Smckusick */ 36455405Smckusick (void)chgproccnt(p->p_cred->p_ruid, -1); 36555405Smckusick 36655405Smckusick /* 36755405Smckusick * Free up credentials. 36855405Smckusick */ 36950200Skarels if (--p->p_cred->p_refcnt == 0) { 37050200Skarels crfree(p->p_cred->pc_ucred); 37150200Skarels FREE(p->p_cred, M_SUBPROC); 37250200Skarels } 37347540Skarels 37447540Skarels /* 37565116Spendry * Release reference to text vnode 37665116Spendry */ 37765116Spendry if (p->p_textvp) 37865116Spendry vrele(p->p_textvp); 37965116Spendry 38065116Spendry /* 38147540Skarels * Finally finished with old proc entry. 38247540Skarels * Unlink it from its process group and free it. 38347540Skarels */ 38447540Skarels leavepgrp(p); 38564582Sbostic if (*p->p_prev = p->p_next) /* off zombproc */ 38664582Sbostic p->p_next->p_prev = p->p_prev; 38712790Ssam if (q = p->p_ysptr) 38812790Ssam q->p_osptr = p->p_osptr; 38912790Ssam if (q = p->p_osptr) 39012790Ssam q->p_ysptr = p->p_ysptr; 39112790Ssam if ((q = p->p_pptr)->p_cptr == p) 39212790Ssam q->p_cptr = p->p_osptr; 39349690Swilliam 39450200Skarels /* 39550200Skarels * Give machine-dependent layer a chance 39650200Skarels * to free anything that cpu_exit couldn't 39750200Skarels * release while still running in process context. 39850200Skarels */ 39950200Skarels cpu_wait(p); 40047540Skarels FREE(p, M_PROC); 40147540Skarels nprocs--; 40244404Skarels return (0); 40312790Ssam } 40464582Sbostic if (p->p_stat == SSTOP && (p->p_flag & P_WAITED) == 0 && 40564582Sbostic (p->p_flag & P_TRACED || uap->options & WUNTRACED)) { 40664582Sbostic p->p_flag |= P_WAITED; 40742927Smckusick retval[0] = p->p_pid; 40837328Skarels #ifdef COMPAT_43 40939737Smckusick if (uap->compat) { 41043895Skarels retval[1] = W_STOPCODE(p->p_xstat); 41139737Smckusick error = 0; 41239737Smckusick } else 41337328Skarels #endif 41437328Skarels if (uap->status) { 41543895Skarels status = W_STOPCODE(p->p_xstat); 41639410Skarels error = copyout((caddr_t)&status, 41751015Sralph (caddr_t)uap->status, sizeof(status)); 41839410Skarels } else 41939410Skarels error = 0; 42044404Skarels return (error); 42112790Ssam } 42212790Ssam } 42347540Skarels if (nfound == 0) 42444404Skarels return (ECHILD); 42537328Skarels if (uap->options & WNOHANG) { 42642927Smckusick retval[0] = 0; 42744404Skarels return (0); 42812790Ssam } 42942927Smckusick if (error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0)) 43044404Skarels return (error); 43112790Ssam goto loop; 43212790Ssam } 43354338Smckusick 43454338Smckusick /* 43554338Smckusick * make process 'parent' the new parent of process 'child'. 43654338Smckusick */ 43754338Smckusick void 43854338Smckusick proc_reparent(child, parent) 43954338Smckusick register struct proc *child; 44054338Smckusick register struct proc *parent; 44154338Smckusick { 44254338Smckusick register struct proc *o; 44354338Smckusick register struct proc *y; 44454338Smckusick 44554338Smckusick if (child->p_pptr == parent) 44654338Smckusick return; 44754338Smckusick 44854338Smckusick /* fix up the child linkage for the old parent */ 44954338Smckusick o = child->p_osptr; 45054338Smckusick y = child->p_ysptr; 45154338Smckusick if (y) 45254338Smckusick y->p_osptr = o; 45354338Smckusick if (o) 45454338Smckusick o->p_ysptr = y; 45554338Smckusick if (child->p_pptr->p_cptr == child) 45654338Smckusick child->p_pptr->p_cptr = o; 45754338Smckusick 45854338Smckusick /* fix up child linkage for new parent */ 45954338Smckusick o = parent->p_cptr; 46054338Smckusick if (o) 46154338Smckusick o->p_ysptr = child; 46254338Smckusick child->p_osptr = o; 46354338Smckusick child->p_ysptr = NULL; 46454338Smckusick parent->p_cptr = child; 46554338Smckusick child->p_pptr = parent; 46654338Smckusick } 467