Annotation of 43BSDReno/sys/kern/kern_exit.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution is only permitted until one year after the first shipment
                      6:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
                      7:  * binary forms are permitted provided that: (1) source distributions retain
                      8:  * this entire copyright notice and comment, and (2) distributions including
                      9:  * binaries display the following acknowledgement:  This product includes
                     10:  * software developed by the University of California, Berkeley and its
                     11:  * contributors'' in the documentation or other materials provided with the
                     12:  * distribution and in all advertising materials mentioning features or use
                     13:  * of this software.  Neither the name of the University nor the names of
                     14:  * its contributors may be used to endorse or promote products derived from
                     15:  * this software without specific prior written permission.
                     16:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     17:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     18:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     19:  *
                     20:  *     @(#)kern_exit.c 7.26 (Berkeley) 6/28/90
                     21:  */
                     22: 
                     23: #include "param.h"
                     24: #include "systm.h"
                     25: #include "map.h"
                     26: #include "ioctl.h"
                     27: #include "tty.h"
                     28: #include "user.h"
                     29: #include "kernel.h"
                     30: #include "proc.h"
                     31: #include "buf.h"
                     32: #include "wait.h"
                     33: #include "vm.h"
                     34: #include "file.h"
                     35: #include "vnode.h"
                     36: #include "syslog.h"
                     37: #include "malloc.h"
                     38: 
                     39: #include "machine/reg.h"
                     40: #ifdef COMPAT_43
                     41: #include "machine/psl.h"
                     42: #endif
                     43: 
                     44: /*
                     45:  * Exit system call: pass back caller's arg
                     46:  */
                     47: /* ARGSUSED */
                     48: rexit(p, uap, retval)
                     49:        struct proc *p;
                     50:        struct args {
                     51:                int     rval;
                     52:        } *uap;
                     53:        int *retval;
                     54: {
                     55: 
                     56:        return (exit(p, W_EXITCODE(uap->rval, 0)));
                     57: }
                     58: 
                     59: /*
                     60:  * Release resources.
                     61:  * Save u. area for parent to look at.
                     62:  * Enter zombie state.
                     63:  * Wake up parent and init processes,
                     64:  * and dispose of children.
                     65:  */
                     66: exit(p, rv)
                     67:        struct proc *p;
                     68:        int rv;
                     69: {
                     70:        register int i;
                     71:        register struct proc *q, *nq;
                     72:        register struct proc **pp;
                     73: 
                     74: #ifdef PGINPROF
                     75:        vmsizmon();
                     76: #endif
                     77:        MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage),
                     78:                M_ZOMBIE, M_WAITOK);
                     79:        p->p_flag &= ~(STRC|SULOCK);
                     80:        p->p_flag |= SWEXIT;
                     81:        p->p_sigignore = ~0;
                     82:        p->p_sig = 0;
                     83:        p->p_cpticks = 0;
                     84:        p->p_pctcpu = 0;
                     85:        for (i = 0; i < NSIG; i++)
                     86:                u.u_signal[i] = SIG_IGN;
                     87:        untimeout(realitexpire, (caddr_t)p);
                     88:        /*
                     89:         * Release virtual memory.  If we resulted from
                     90:         * a vfork(), instead give the resources back to
                     91:         * the parent.
                     92:         */
                     93:        if ((p->p_flag & SVFORK) == 0) {
                     94: #ifdef MAPMEM
                     95:                if (u.u_mmap)
                     96:                        (void) mmexit(p);
                     97: #endif
                     98:                vrelvm();
                     99:        } else {
                    100:                p->p_flag &= ~SVFORK;
                    101:                wakeup((caddr_t)p);
                    102:                while ((p->p_flag & SVFDONE) == 0)
                    103:                        sleep((caddr_t)p, PZERO - 1);
                    104:                p->p_flag &= ~SVFDONE;
                    105:        }
                    106:        for (i = 0; i <= u.u_lastfile; i++) {
                    107:                struct file *f;
                    108: 
                    109:                f = u.u_ofile[i];
                    110:                if (f) {
                    111:                        u.u_ofile[i] = NULL;
                    112:                        u.u_pofile[i] = 0;
                    113:                        (void) closef(f);
                    114:                }
                    115:        }
                    116:        if (SESS_LEADER(p)) {
                    117:                register struct session *sp = p->p_session;
                    118: 
                    119:                if (sp->s_ttyvp) {
                    120:                        /*
                    121:                         * Controlling process.
                    122:                         * Signal foreground pgrp and revoke access
                    123:                         * to controlling terminal.
                    124:                         */
                    125:                        if (sp->s_ttyp->t_pgrp)
                    126:                                pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
                    127:                        vgoneall(sp->s_ttyvp);
                    128:                        vrele(sp->s_ttyvp);
                    129:                        sp->s_ttyvp = NULL;
                    130:                        /*
                    131:                         * s_ttyp is not zero'd; we use this to indicate
                    132:                         * that the session once had a controlling terminal.
                    133:                         * (for logging and informational purposes)
                    134:                         */
                    135:                }
                    136:                sp->s_leader = 0;
                    137:        }
                    138:        VOP_LOCK(u.u_cdir);
                    139:        vput(u.u_cdir);
                    140:        if (u.u_rdir) {
                    141:                VOP_LOCK(u.u_rdir);
                    142:                vput(u.u_rdir);
                    143:        }
                    144:        u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
                    145:        (void) acct(p);
                    146:        crfree(u.u_cred);
                    147: #ifdef KTRACE
                    148:        /* 
                    149:         * release trace file
                    150:         */
                    151:        if (p->p_tracep)
                    152:                vrele(p->p_tracep);
                    153: #endif
                    154:        /*
                    155:         * Freeing the user structure and kernel stack
                    156:         * for the current process: have to run a bit longer
                    157:         * using the pages which are about to be freed...
                    158:         * vrelu will block memory allocation by raising ipl.
                    159:         */
                    160:        vrelu(p, 0);
                    161:        vrelpt(p);
                    162:        if (*p->p_prev = p->p_nxt)              /* off allproc queue */
                    163:                p->p_nxt->p_prev = p->p_prev;
                    164:        if (p->p_nxt = zombproc)                /* onto zombproc */
                    165:                p->p_nxt->p_prev = &p->p_nxt;
                    166:        p->p_prev = &zombproc;
                    167:        zombproc = p;
                    168:        multprog--;
                    169:        p->p_stat = SZOMB;
                    170:        noproc = 1;
                    171:        for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash)
                    172:                if (*pp == p) {
                    173:                        *pp = p->p_hash;
                    174:                        goto done;
                    175:                }
                    176:        panic("exit");
                    177: done:
                    178:        if (p->p_pid == 1) {
                    179:                if (p->p_dsize == 0) {
                    180:                        printf("Can't exec init (errno %d)\n", WEXITSTATUS(rv));
                    181:                        for (;;)
                    182:                                ;
                    183:                } else
                    184:                        panic("init died");
                    185:        }
                    186:        p->p_xstat = rv;
                    187:        *p->p_ru = u.u_ru;
                    188:        i = splclock();
                    189:        p->p_ru->ru_stime = p->p_stime;
                    190:        p->p_ru->ru_utime = p->p_utime;
                    191:        splx(i);
                    192:        ruadd(p->p_ru, &u.u_cru);
                    193:        if (p->p_cptr)          /* only need this if any child is S_ZOMB */
                    194:                wakeup((caddr_t)&proc[1]);
                    195:        fixjobc(p, 0);
                    196:        for (q = p->p_cptr; q != NULL; q = nq) {
                    197:                nq = q->p_osptr;
                    198:                if (nq != NULL)
                    199:                        nq->p_ysptr = NULL;
                    200:                if (proc[1].p_cptr)
                    201:                        proc[1].p_cptr->p_ysptr = q;
                    202:                q->p_osptr = proc[1].p_cptr;
                    203:                q->p_ysptr = NULL;
                    204:                proc[1].p_cptr = q;
                    205: 
                    206:                q->p_pptr = &proc[1];
                    207:                q->p_ppid = 1;
                    208:                /*
                    209:                 * Traced processes are killed
                    210:                 * since their existence means someone is screwing up.
                    211:                 */
                    212:                if (q->p_flag&STRC) {
                    213:                        q->p_flag &= ~STRC;
                    214:                        psignal(q, SIGKILL);
                    215:                }
                    216:        }
                    217:        p->p_cptr = NULL;
                    218:        psignal(p->p_pptr, SIGCHLD);
                    219:        wakeup((caddr_t)p->p_pptr);
                    220: #if defined(tahoe)
                    221:        dkeyrelease(p->p_dkey), p->p_dkey = 0;
                    222:        ckeyrelease(p->p_ckey), p->p_ckey = 0;
                    223:        u.u_pcb.pcb_savacc.faddr = (float *)NULL;
                    224: #endif
                    225:        swtch();
                    226: }
                    227: 
                    228: #ifdef COMPAT_43
                    229: owait(p, uap, retval)
                    230:        struct proc *p;
                    231:        register struct args {
                    232:                int     pid;
                    233:                int     *status;
                    234:                int     options;
                    235:                struct  rusage *rusage;
                    236:                int     compat;
                    237:        } *uap;
                    238:        int *retval;
                    239: {
                    240: 
                    241:        if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) {
                    242:                uap->options = 0;
                    243:                uap->rusage = 0;
                    244:        } else {
                    245:                uap->options = u.u_ar0[R0];
                    246:                uap->rusage = (struct rusage *)u.u_ar0[R1];
                    247:        }
                    248:        uap->pid = WAIT_ANY;
                    249:        uap->status = 0;
                    250:        uap->compat = 1;
                    251:        return (wait1(p, uap, retval));
                    252: }
                    253: 
                    254: wait4(p, uap, retval)
                    255:        struct proc *p;
                    256:        struct args {
                    257:                int     pid;
                    258:                int     *status;
                    259:                int     options;
                    260:                struct  rusage *rusage;
                    261:                int     compat;
                    262:        } *uap;
                    263:        int *retval;
                    264: {
                    265: 
                    266:        uap->compat = 0;
                    267:        return (wait1(p, uap, retval));
                    268: }
                    269: #else
                    270: #define        wait1   wait4
                    271: #endif
                    272: 
                    273: /*
                    274:  * Wait system call.
                    275:  * Search for a terminated (zombie) child,
                    276:  * finally lay it to rest, and collect its status.
                    277:  * Look also for stopped (traced) children,
                    278:  * and pass back status from them.
                    279:  */
                    280: wait1(q, uap, retval)
                    281:        register struct proc *q;
                    282:        register struct args {
                    283:                int     pid;
                    284:                int     *status;
                    285:                int     options;
                    286:                struct  rusage *rusage;
                    287: #ifdef COMPAT_43
                    288:                int compat;
                    289: #endif
                    290:        } *uap;
                    291:        int retval[];
                    292: {
                    293:        register int f;
                    294:        register struct proc *p;
                    295:        int status, error;
                    296: 
                    297:        if (uap->pid == 0)
                    298:                uap->pid = -q->p_pgid;
                    299: #ifdef notyet
                    300:        if (uap->options &~ (WUNTRACED|WNOHANG))
                    301:                return (EINVAL);
                    302: #endif
                    303: loop:
                    304:        f = 0;
                    305:        for (p = q->p_cptr; p; p = p->p_osptr) {
                    306:                if (uap->pid != WAIT_ANY &&
                    307:                    p->p_pid != uap->pid && p->p_pgid != -uap->pid)
                    308:                        continue;
                    309:                f++;
                    310:                if (p->p_stat == SZOMB) {
                    311:                        retval[0] = p->p_pid;
                    312: #ifdef COMPAT_43
                    313:                        if (uap->compat)
                    314:                                retval[1] = p->p_xstat;
                    315:                        else
                    316: #endif
                    317:                        if (uap->status) {
                    318:                                status = p->p_xstat;    /* convert to int */
                    319:                                if (error = copyout((caddr_t)&status,
                    320:                                    (caddr_t)uap->status, sizeof(status)))
                    321:                                        return (error);
                    322:                        }
                    323:                        if (uap->rusage && (error = copyout((caddr_t)p->p_ru,
                    324:                            (caddr_t)uap->rusage, sizeof (struct rusage))))
                    325:                                return (error);
                    326:                        pgrm(p);                        /* off pgrp */
                    327:                        p->p_xstat = 0;
                    328:                        ruadd(&u.u_cru, p->p_ru);
                    329:                        FREE(p->p_ru, M_ZOMBIE);
                    330:                        p->p_ru = 0;
                    331:                        p->p_stat = NULL;
                    332:                        p->p_pid = 0;
                    333:                        p->p_ppid = 0;
                    334:                        if (*p->p_prev = p->p_nxt)      /* off zombproc */
                    335:                                p->p_nxt->p_prev = p->p_prev;
                    336:                        p->p_nxt = freeproc;            /* onto freeproc */
                    337:                        freeproc = p;
                    338:                        if (q = p->p_ysptr)
                    339:                                q->p_osptr = p->p_osptr;
                    340:                        if (q = p->p_osptr)
                    341:                                q->p_ysptr = p->p_ysptr;
                    342:                        if ((q = p->p_pptr)->p_cptr == p)
                    343:                                q->p_cptr = p->p_osptr;
                    344:                        p->p_pptr = 0;
                    345:                        p->p_ysptr = 0;
                    346:                        p->p_osptr = 0;
                    347:                        p->p_cptr = 0;
                    348:                        p->p_sig = 0;
                    349:                        p->p_sigcatch = 0;
                    350:                        p->p_sigignore = 0;
                    351:                        p->p_sigmask = 0;
                    352:                        /*p->p_pgrp = 0;*/
                    353:                        p->p_flag = 0;
                    354:                        p->p_wchan = 0;
                    355:                        return (0);
                    356:                }
                    357:                if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 &&
                    358:                    (p->p_flag & STRC || uap->options & WUNTRACED)) {
                    359:                        p->p_flag |= SWTED;
                    360:                        retval[0] = p->p_pid;
                    361: #ifdef COMPAT_43
                    362:                        if (uap->compat) {
                    363:                                retval[1] = W_STOPCODE(p->p_xstat);
                    364:                                error = 0;
                    365:                        } else
                    366: #endif
                    367:                        if (uap->status) {
                    368:                                status = W_STOPCODE(p->p_xstat);
                    369:                                error = copyout((caddr_t)&status,
                    370:                                    (caddr_t)uap->status, sizeof(status));
                    371:                        } else
                    372:                                error = 0;
                    373:                        return (error);
                    374:                }
                    375:        }
                    376:        if (f == 0)
                    377:                return (ECHILD);
                    378:        if (uap->options & WNOHANG) {
                    379:                retval[0] = 0;
                    380:                return (0);
                    381:        }
                    382:        if (error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0))
                    383:                return (error);
                    384:        goto loop;
                    385: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.