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*45673Skarels * @(#)kern_exit.c 7.28 (Berkeley) 12/01/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 "vm.h" 2117090Sbloom #include "file.h" 2237728Smckusick #include "vnode.h" 2318638Ssam #include "syslog.h" 2432018Smckusick #include "malloc.h" 2512790Ssam 2637520Smckusick #include "machine/reg.h" 2737328Skarels #ifdef COMPAT_43 2837520Smckusick #include "machine/psl.h" 2937328Skarels #endif 3037328Skarels 3112790Ssam /* 3212790Ssam * Exit system call: pass back caller's arg 3312790Ssam */ 3442927Smckusick /* ARGSUSED */ 3542927Smckusick rexit(p, uap, retval) 3642927Smckusick struct proc *p; 3742927Smckusick struct args { 3812790Ssam int rval; 3912790Ssam } *uap; 4042927Smckusick int *retval; 4142927Smckusick { 4212790Ssam 4345157Skarels exit(p, W_EXITCODE(uap->rval, 0)); 4445157Skarels /* NOTREACHED */ 4512790Ssam } 4612790Ssam 4712790Ssam /* 4812790Ssam * Release resources. 4912790Ssam * Save u. area for parent to look at. 5012790Ssam * Enter zombie state. 5112790Ssam * Wake up parent and init processes, 5212790Ssam * and dispose of children. 5312790Ssam */ 5442927Smckusick exit(p, rv) 5542927Smckusick struct proc *p; 5638930Skarels int rv; 5712790Ssam { 5812790Ssam register int i; 5942927Smckusick register struct proc *q, *nq; 6040670Skarels register struct proc **pp; 6112790Ssam 6212790Ssam #ifdef PGINPROF 6312790Ssam vmsizmon(); 6412790Ssam #endif 6532018Smckusick MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage), 6632018Smckusick M_ZOMBIE, M_WAITOK); 6712790Ssam p->p_flag &= ~(STRC|SULOCK); 6812790Ssam p->p_flag |= SWEXIT; 6912882Ssam p->p_sigignore = ~0; 7039410Skarels p->p_sig = 0; 7112790Ssam p->p_cpticks = 0; 7212790Ssam p->p_pctcpu = 0; 7312882Ssam for (i = 0; i < NSIG; i++) 7412790Ssam u.u_signal[i] = SIG_IGN; 7512790Ssam untimeout(realitexpire, (caddr_t)p); 7612790Ssam /* 7712790Ssam * Release virtual memory. If we resulted from 7812790Ssam * a vfork(), instead give the resources back to 7912790Ssam * the parent. 8012790Ssam */ 8141569Smckusick if ((p->p_flag & SVFORK) == 0) { 8241569Smckusick #ifdef MAPMEM 8341569Smckusick if (u.u_mmap) 8442927Smckusick (void) mmexit(p); 8541569Smckusick #endif 8612790Ssam vrelvm(); 8741569Smckusick } else { 8812790Ssam p->p_flag &= ~SVFORK; 8912790Ssam wakeup((caddr_t)p); 9012790Ssam while ((p->p_flag & SVFDONE) == 0) 9112790Ssam sleep((caddr_t)p, PZERO - 1); 9212790Ssam p->p_flag &= ~SVFDONE; 9312790Ssam } 9421105Skarels for (i = 0; i <= u.u_lastfile; i++) { 9512790Ssam struct file *f; 9612790Ssam 9712790Ssam f = u.u_ofile[i]; 9821105Skarels if (f) { 9921105Skarels u.u_ofile[i] = NULL; 10021105Skarels u.u_pofile[i] = 0; 10139351Smckusick (void) closef(f); 10221105Skarels } 10312790Ssam } 10437328Skarels if (SESS_LEADER(p)) { 10542897Smarc register struct session *sp = p->p_session; 10642897Smarc 10742897Smarc if (sp->s_ttyvp) { 10840809Smarc /* 10942897Smarc * Controlling process. 11042897Smarc * Signal foreground pgrp and revoke access 11142897Smarc * to controlling terminal. 11242897Smarc */ 11342897Smarc if (sp->s_ttyp->t_pgrp) 11442916Smarc pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); 11542897Smarc vgoneall(sp->s_ttyvp); 11642897Smarc vrele(sp->s_ttyvp); 11742897Smarc sp->s_ttyvp = NULL; 11842897Smarc /* 11940809Smarc * s_ttyp is not zero'd; we use this to indicate 12040809Smarc * that the session once had a controlling terminal. 12142897Smarc * (for logging and informational purposes) 12240809Smarc */ 12337328Skarels } 12442897Smarc sp->s_leader = 0; 12537328Skarels } 12637728Smckusick VOP_LOCK(u.u_cdir); 12737728Smckusick vput(u.u_cdir); 12812790Ssam if (u.u_rdir) { 12937728Smckusick VOP_LOCK(u.u_rdir); 13037728Smckusick vput(u.u_rdir); 13112790Ssam } 13212790Ssam u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; 13343380Smckusick (void) acct(p); 13437728Smckusick crfree(u.u_cred); 13537328Skarels #ifdef KTRACE 13637328Skarels /* 13737328Skarels * release trace file 13837328Skarels */ 13937328Skarels if (p->p_tracep) 14037728Smckusick vrele(p->p_tracep); 14137328Skarels #endif 14226823Skarels /* 14326823Skarels * Freeing the user structure and kernel stack 14426823Skarels * for the current process: have to run a bit longer 14526823Skarels * using the pages which are about to be freed... 14626823Skarels * vrelu will block memory allocation by raising ipl. 14726823Skarels */ 14842927Smckusick vrelu(p, 0); 14942927Smckusick vrelpt(p); 15016527Skarels if (*p->p_prev = p->p_nxt) /* off allproc queue */ 15116527Skarels p->p_nxt->p_prev = p->p_prev; 15216527Skarels if (p->p_nxt = zombproc) /* onto zombproc */ 15316527Skarels p->p_nxt->p_prev = &p->p_nxt; 15416527Skarels p->p_prev = &zombproc; 15516527Skarels zombproc = p; 15612790Ssam multprog--; 15712790Ssam p->p_stat = SZOMB; 15812790Ssam noproc = 1; 15940670Skarels for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash) 16040670Skarels if (*pp == p) { 16140670Skarels *pp = p->p_hash; 16240670Skarels goto done; 16340670Skarels } 16440670Skarels panic("exit"); 16540670Skarels done: 16621105Skarels if (p->p_pid == 1) { 16721105Skarels if (p->p_dsize == 0) { 16839410Skarels printf("Can't exec init (errno %d)\n", WEXITSTATUS(rv)); 16921105Skarels for (;;) 17021105Skarels ; 17121105Skarels } else 17221105Skarels panic("init died"); 17321105Skarels } 17412790Ssam p->p_xstat = rv; 17521105Skarels *p->p_ru = u.u_ru; 17640809Smarc i = splclock(); 17740809Smarc p->p_ru->ru_stime = p->p_stime; 17840809Smarc p->p_ru->ru_utime = p->p_utime; 17940809Smarc splx(i); 18021105Skarels ruadd(p->p_ru, &u.u_cru); 18116527Skarels if (p->p_cptr) /* only need this if any child is S_ZOMB */ 18216527Skarels wakeup((caddr_t)&proc[1]); 183*45673Skarels fixjobc(p, p->p_pgrp, 0); 18416527Skarels for (q = p->p_cptr; q != NULL; q = nq) { 18516527Skarels nq = q->p_osptr; 18616527Skarels if (nq != NULL) 18716527Skarels nq->p_ysptr = NULL; 18816527Skarels if (proc[1].p_cptr) 18916527Skarels proc[1].p_cptr->p_ysptr = q; 19016527Skarels q->p_osptr = proc[1].p_cptr; 19116527Skarels q->p_ysptr = NULL; 19216527Skarels proc[1].p_cptr = q; 19312790Ssam 19416527Skarels q->p_pptr = &proc[1]; 19516527Skarels q->p_ppid = 1; 19616527Skarels /* 19716527Skarels * Traced processes are killed 19816527Skarels * since their existence means someone is screwing up. 19916527Skarels */ 20016527Skarels if (q->p_flag&STRC) { 20116527Skarels q->p_flag &= ~STRC; 20216527Skarels psignal(q, SIGKILL); 20312790Ssam } 20416527Skarels } 20517540Skarels p->p_cptr = NULL; 20612790Ssam psignal(p->p_pptr, SIGCHLD); 20712790Ssam wakeup((caddr_t)p->p_pptr); 20829946Skarels #if defined(tahoe) 20929946Skarels dkeyrelease(p->p_dkey), p->p_dkey = 0; 21029946Skarels ckeyrelease(p->p_ckey), p->p_ckey = 0; 21129946Skarels u.u_pcb.pcb_savacc.faddr = (float *)NULL; 21229946Skarels #endif 21312790Ssam swtch(); 21412790Ssam } 21512790Ssam 21637328Skarels #ifdef COMPAT_43 21742927Smckusick owait(p, uap, retval) 21842927Smckusick struct proc *p; 21942927Smckusick register struct args { 22037328Skarels int pid; 22139410Skarels int *status; 22237328Skarels int options; 22337328Skarels struct rusage *rusage; 22439410Skarels int compat; 22542927Smckusick } *uap; 22642927Smckusick int *retval; 22742927Smckusick { 22812790Ssam 22912790Ssam if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { 23038930Skarels uap->options = 0; 23137328Skarels uap->rusage = 0; 23237328Skarels } else { 23338930Skarels uap->options = u.u_ar0[R0]; 23437328Skarels uap->rusage = (struct rusage *)u.u_ar0[R1]; 23512790Ssam } 23637328Skarels uap->pid = WAIT_ANY; 23737328Skarels uap->status = 0; 23839410Skarels uap->compat = 1; 23944404Skarels return (wait1(p, uap, retval)); 24012790Ssam } 24112790Ssam 24242927Smckusick wait4(p, uap, retval) 24342927Smckusick struct proc *p; 24442927Smckusick struct args { 24539410Skarels int pid; 24639410Skarels int *status; 24739410Skarels int options; 24839410Skarels struct rusage *rusage; 24939410Skarels int compat; 25042927Smckusick } *uap; 25142927Smckusick int *retval; 25242927Smckusick { 25339410Skarels 25439410Skarels uap->compat = 0; 25544404Skarels return (wait1(p, uap, retval)); 25637328Skarels } 25739410Skarels #else 25839410Skarels #define wait1 wait4 25937328Skarels #endif 26037328Skarels 26112790Ssam /* 26212790Ssam * Wait system call. 26312790Ssam * Search for a terminated (zombie) child, 26412790Ssam * finally lay it to rest, and collect its status. 26512790Ssam * Look also for stopped (traced) children, 26612790Ssam * and pass back status from them. 26712790Ssam */ 26842927Smckusick wait1(q, uap, retval) 26942927Smckusick register struct proc *q; 27042927Smckusick register struct args { 27137328Skarels int pid; 27239410Skarels int *status; 27337328Skarels int options; 27437328Skarels struct rusage *rusage; 27539410Skarels #ifdef COMPAT_43 27639410Skarels int compat; 27739410Skarels #endif 27842927Smckusick } *uap; 27942927Smckusick int retval[]; 28042927Smckusick { 28142927Smckusick register int f; 28242927Smckusick register struct proc *p; 28339410Skarels int status, error; 28412790Ssam 28537328Skarels if (uap->pid == 0) 28637328Skarels uap->pid = -q->p_pgid; 28738930Skarels #ifdef notyet 28839410Skarels if (uap->options &~ (WUNTRACED|WNOHANG)) 28944404Skarels return (EINVAL); 29038930Skarels #endif 29112790Ssam loop: 29238930Skarels f = 0; 29316527Skarels for (p = q->p_cptr; p; p = p->p_osptr) { 29437328Skarels if (uap->pid != WAIT_ANY && 29537328Skarels p->p_pid != uap->pid && p->p_pgid != -uap->pid) 29637328Skarels continue; 29712790Ssam f++; 29812790Ssam if (p->p_stat == SZOMB) { 29942927Smckusick retval[0] = p->p_pid; 30037328Skarels #ifdef COMPAT_43 30139410Skarels if (uap->compat) 30242927Smckusick retval[1] = p->p_xstat; 30337328Skarels else 30437328Skarels #endif 30537328Skarels if (uap->status) { 30639410Skarels status = p->p_xstat; /* convert to int */ 30739410Skarels if (error = copyout((caddr_t)&status, 30837328Skarels (caddr_t)uap->status, sizeof(status))) 30944404Skarels return (error); 31037328Skarels } 31139410Skarels if (uap->rusage && (error = copyout((caddr_t)p->p_ru, 31239410Skarels (caddr_t)uap->rusage, sizeof (struct rusage)))) 31344404Skarels return (error); 31439410Skarels pgrm(p); /* off pgrp */ 31512790Ssam p->p_xstat = 0; 31637328Skarels ruadd(&u.u_cru, p->p_ru); 31737328Skarels FREE(p->p_ru, M_ZOMBIE); 31837328Skarels p->p_ru = 0; 31912790Ssam p->p_stat = NULL; 32012790Ssam p->p_pid = 0; 32112790Ssam p->p_ppid = 0; 32216527Skarels if (*p->p_prev = p->p_nxt) /* off zombproc */ 32316527Skarels p->p_nxt->p_prev = p->p_prev; 32416527Skarels p->p_nxt = freeproc; /* onto freeproc */ 32516527Skarels freeproc = p; 32612790Ssam if (q = p->p_ysptr) 32712790Ssam q->p_osptr = p->p_osptr; 32812790Ssam if (q = p->p_osptr) 32912790Ssam q->p_ysptr = p->p_ysptr; 33012790Ssam if ((q = p->p_pptr)->p_cptr == p) 33112790Ssam q->p_cptr = p->p_osptr; 33212790Ssam p->p_pptr = 0; 33312790Ssam p->p_ysptr = 0; 33412790Ssam p->p_osptr = 0; 33512790Ssam p->p_cptr = 0; 33612790Ssam p->p_sig = 0; 33712882Ssam p->p_sigcatch = 0; 33812882Ssam p->p_sigignore = 0; 33912882Ssam p->p_sigmask = 0; 34037328Skarels /*p->p_pgrp = 0;*/ 34112790Ssam p->p_flag = 0; 34212790Ssam p->p_wchan = 0; 34344404Skarels return (0); 34412790Ssam } 34537328Skarels if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 && 34637328Skarels (p->p_flag & STRC || uap->options & WUNTRACED)) { 34712790Ssam p->p_flag |= SWTED; 34842927Smckusick retval[0] = p->p_pid; 34937328Skarels #ifdef COMPAT_43 35039737Smckusick if (uap->compat) { 35143895Skarels retval[1] = W_STOPCODE(p->p_xstat); 35239737Smckusick error = 0; 35339737Smckusick } else 35437328Skarels #endif 35537328Skarels if (uap->status) { 35643895Skarels status = W_STOPCODE(p->p_xstat); 35739410Skarels error = copyout((caddr_t)&status, 35837328Skarels (caddr_t)uap->status, sizeof(status)); 35939410Skarels } else 36039410Skarels error = 0; 36144404Skarels return (error); 36212790Ssam } 36312790Ssam } 36439410Skarels if (f == 0) 36544404Skarels return (ECHILD); 36637328Skarels if (uap->options & WNOHANG) { 36742927Smckusick retval[0] = 0; 36844404Skarels return (0); 36912790Ssam } 37042927Smckusick if (error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0)) 37144404Skarels return (error); 37212790Ssam goto loop; 37312790Ssam } 374