Annotation of 43BSDReno/sys/kern/kern_exit.c, revision 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.