Annotation of Net2/kern/kern_exit.c, revision 1.1.1.4

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This product includes software developed by the University of
                     16:  *     California, Berkeley and its contributors.
                     17:  * 4. Neither the name of the University nor the names of its contributors
                     18:  *    may be used to endorse or promote products derived from this software
                     19:  *    without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     31:  * SUCH DAMAGE.
                     32:  *
1.1.1.4 ! root       33:  *     from: @(#)kern_exit.c   7.35 (Berkeley) 6/27/91
        !            34:  *     kern_exit.c,v 1.7 1993/07/13 22:13:20 cgd Exp
1.1       root       35:  */
                     36: 
                     37: #include "param.h"
                     38: #include "systm.h"
                     39: #include "ioctl.h"
                     40: #include "tty.h"
                     41: #include "time.h"
                     42: #include "resource.h"
                     43: #include "kernel.h"
                     44: #include "proc.h"
                     45: #include "buf.h"
                     46: #include "wait.h"
                     47: #include "file.h"
                     48: #include "vnode.h"
                     49: #include "syslog.h"
                     50: #include "malloc.h"
                     51: #include "resourcevar.h"
1.1.1.4 ! root       52: #ifdef ACCOUNTING
        !            53: #include "acct.h"
        !            54: #endif
1.1       root       55: 
                     56: #include "machine/cpu.h"
                     57: #ifdef COMPAT_43
                     58: #include "machine/reg.h"
                     59: #include "machine/psl.h"
                     60: #endif
                     61: 
                     62: #include "vm/vm.h"
                     63: #include "vm/vm_kern.h"
                     64: 
1.1.1.4 ! root       65: volatile void exit __P((struct proc *p, int rv));
        !            66: 
1.1       root       67: /*
                     68:  * Exit system call: pass back caller's arg
                     69:  */
1.1.1.4 ! root       70: 
        !            71: struct rexit_args {
        !            72:        int     rval;
        !            73: };
        !            74: 
1.1       root       75: /* ARGSUSED */
1.1.1.4 ! root       76: volatile void
1.1       root       77: rexit(p, uap, retval)
                     78:        struct proc *p;
1.1.1.4 ! root       79:        struct rexit_args *uap;
1.1       root       80:        int *retval;
                     81: {
                     82: 
1.1.1.4 ! root       83:        kexit(p, W_EXITCODE(uap->rval, 0));
1.1       root       84:        /* NOTREACHED */
                     85: }
                     86: 
                     87: /*
                     88:  * Exit: deallocate address space and other resources,
                     89:  * change proc state to zombie, and unlink proc from allproc
                     90:  * and parent's lists.  Save exit status and rusage for wait().
                     91:  * Check for child processes and orphan them.
                     92:  */
1.1.1.4 ! root       93: volatile void
        !            94: kexit(p, rv)
1.1       root       95:        register struct proc *p;
                     96:        int rv;
                     97: {
                     98:        register struct proc *q, *nq;
                     99:        register struct proc **pp;
                    100: 
                    101: #ifdef PGINPROF
                    102:        vmsizmon();
                    103: #endif
                    104:        MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage),
                    105:                M_ZOMBIE, M_WAITOK);
                    106:        /*
                    107:         * If parent is waiting for us to exit or exec,
                    108:         * SPPWAIT is set; we will wakeup the parent below.
                    109:         */
                    110:        p->p_flag &= ~(STRC|SPPWAIT);
                    111:        p->p_flag |= SWEXIT;
                    112:        p->p_sigignore = ~0;
                    113:        p->p_sig = 0;
1.1.1.4 ! root      114:        untimeout((timeout_t)realitexpire, (caddr_t)p);
1.1       root      115: 
                    116:        /*
                    117:         * Close open files and release open-file table.
                    118:         * This may block!
                    119:         */
                    120:        fdfree(p);
                    121: 
                    122:        /* The next two chunks should probably be moved to vmspace_exit. */
                    123: #ifdef SYSVSHM
                    124:        if (p->p_vmspace->vm_shm)
                    125:                shmexit(p);
                    126: #endif
                    127:        /*
                    128:         * Release user portion of address space.
                    129:         * This releases references to vnodes,
                    130:         * which could cause I/O if the file has been unlinked.
                    131:         * Need to do this early enough that we can still sleep.
                    132:         * Can't free the entire vmspace as the kernel stack
                    133:         * may be mapped within that space also.
                    134:         */
                    135:        if (p->p_vmspace->vm_refcnt == 1)
                    136:                (void) vm_map_remove(&p->p_vmspace->vm_map, VM_MIN_ADDRESS,
                    137:                    VM_MAXUSER_ADDRESS);
                    138: 
                    139:        if (p->p_pid == 1)
                    140:                panic("init died");
1.1.1.3   root      141: 
1.1       root      142:        if (SESS_LEADER(p)) {
                    143:                register struct session *sp = p->p_session;
                    144: 
                    145:                if (sp->s_ttyvp) {
                    146:                        /*
                    147:                         * Controlling process.
                    148:                         * Signal foreground pgrp,
                    149:                         * drain controlling terminal
                    150:                         * and revoke access to controlling terminal.
                    151:                         */
                    152:                        if (sp->s_ttyp->t_session == sp) {
                    153:                                if (sp->s_ttyp->t_pgrp)
                    154:                                        pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
                    155:                                (void) ttywait(sp->s_ttyp);
                    156:                                vgoneall(sp->s_ttyvp);
                    157:                        }
                    158:                        vrele(sp->s_ttyvp);
                    159:                        sp->s_ttyvp = NULL;
                    160:                        /*
                    161:                         * s_ttyp is not zero'd; we use this to indicate
                    162:                         * that the session once had a controlling terminal.
                    163:                         * (for logging and informational purposes)
                    164:                         */
                    165:                }
                    166:                sp->s_leader = NULL;
                    167:        }
                    168:        fixjobc(p, p->p_pgrp, 0);
                    169:        p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
1.1.1.4 ! root      170: #ifdef ACCOUNTING
        !           171:        (void) acct(p);
        !           172: #endif
1.1       root      173: #ifdef KTRACE
                    174:        /* 
                    175:         * release trace file
                    176:         */
                    177:        if (p->p_tracep)
                    178:                vrele(p->p_tracep);
                    179: #endif
                    180: 
1.1.1.2   root      181:        /* current process does not exist, as far as other parts of the
                    182:         * system (clock) is concerned, since parts of it might not be
                    183:         * there anymore */
                    184:        curproc = NULL;
                    185: 
                    186:        if (--p->p_limit->p_refcnt == 0) {
                    187:                FREE(p->p_limit, M_SUBPROC);
                    188:                p->p_limit = (struct plimit *) -1;
                    189:        }
                    190: 
1.1       root      191:        /*
                    192:         * Remove proc from allproc queue and pidhash chain.
                    193:         * Place onto zombproc.  Unlink from parent's child list.
                    194:         */
                    195:        if (*p->p_prev = p->p_nxt)
                    196:                p->p_nxt->p_prev = p->p_prev;
                    197:        if (p->p_nxt = zombproc)
                    198:                p->p_nxt->p_prev = &p->p_nxt;
                    199:        p->p_prev = &zombproc;
                    200:        zombproc = p;
                    201:        p->p_stat = SZOMB;
                    202:        for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash)
                    203:                if (*pp == p) {
                    204:                        *pp = p->p_hash;
                    205:                        goto done;
                    206:                }
                    207:        panic("exit");
                    208: done:
                    209: 
                    210:        if (p->p_cptr)          /* only need this if any child is S_ZOMB */
                    211:                wakeup((caddr_t) initproc);
                    212:        for (q = p->p_cptr; q != NULL; q = nq) {
                    213:                nq = q->p_osptr;
                    214:                if (nq != NULL)
                    215:                        nq->p_ysptr = NULL;
                    216:                if (initproc->p_cptr)
                    217:                        initproc->p_cptr->p_ysptr = q;
                    218:                q->p_osptr = initproc->p_cptr;
                    219:                q->p_ysptr = NULL;
                    220:                initproc->p_cptr = q;
                    221: 
                    222:                q->p_pptr = initproc;
                    223:                /*
                    224:                 * Traced processes are killed
                    225:                 * since their existence means someone is screwing up.
                    226:                 */
                    227:                if (q->p_flag&STRC) {
                    228:                        q->p_flag &= ~STRC;
                    229:                        psignal(q, SIGKILL);
                    230:                }
                    231:        }
                    232:        p->p_cptr = NULL;
                    233: 
                    234:        /*
                    235:         * Save exit status and final rusage info,
                    236:         * adding in child rusage info and self times.
                    237:         */
                    238:        p->p_xstat = rv;
                    239:        *p->p_ru = p->p_stats->p_ru;
                    240:        p->p_ru->ru_stime = p->p_stime;
                    241:        p->p_ru->ru_utime = p->p_utime;
                    242:        ruadd(p->p_ru, &p->p_stats->p_cru);
                    243: 
                    244:        /*
                    245:         * Notify parent that we're gone.
                    246:         */
                    247:        psignal(p->p_pptr, SIGCHLD);
                    248:        wakeup((caddr_t)p->p_pptr);
                    249: #if defined(tahoe)
                    250:        /* move this to cpu_exit */
                    251:        p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL;
                    252: #endif
                    253:        /*
                    254:         * Finally, call machine-dependent code to release the remaining
                    255:         * resources including address space, the kernel stack and pcb.
                    256:         * The address space is released by "vmspace_free(p->p_vmspace)";
                    257:         * This is machine-dependent, as we may have to change stacks
                    258:         * or ensure that the current one isn't reallocated before we
                    259:         * finish.  cpu_exit will end with a call to swtch(), finishing
                    260:         * our execution (pun intended).
                    261:         */
                    262:        cpu_exit(p);
                    263:        /* NOTREACHED */
                    264: }
                    265: 
                    266: #ifdef COMPAT_43
1.1.1.4 ! root      267: struct owait_args {
        !           268:        int     pid;
        !           269:        int     *status;
        !           270:        int     options;
        !           271:        struct  rusage *rusage;
        !           272:        int     compat;
        !           273: };
        !           274: 
        !           275: int
1.1       root      276: owait(p, uap, retval)
                    277:        struct proc *p;
1.1.1.4 ! root      278:        register struct owait_args *uap;
1.1       root      279:        int *retval;
                    280: {
                    281: 
1.1.1.2   root      282:        uap->options = 0;
                    283:        uap->rusage = 0;
1.1       root      284:        uap->pid = WAIT_ANY;
                    285:        uap->status = 0;
                    286:        uap->compat = 1;
                    287:        return (wait1(p, uap, retval));
                    288: }
                    289: 
1.1.1.4 ! root      290: struct wait4_args {
        !           291:        int     pid;
        !           292:        int     *status;
        !           293:        int     options;
        !           294:        struct  rusage *rusage;
        !           295:        int     compat;
        !           296: };
        !           297: 
        !           298: int
1.1       root      299: wait4(p, uap, retval)
                    300:        struct proc *p;
1.1.1.4 ! root      301:        struct wait4_args *uap;
1.1       root      302:        int *retval;
                    303: {
                    304: 
                    305:        uap->compat = 0;
                    306:        return (wait1(p, uap, retval));
                    307: }
                    308: #else
                    309: #define        wait1   wait4
                    310: #endif
                    311: 
                    312: /*
                    313:  * Wait: check child processes to see if any have exited,
                    314:  * stopped under trace, or (optionally) stopped by a signal.
                    315:  * Pass back status and deallocate exited child's proc structure.
                    316:  */
1.1.1.4 ! root      317: 
        !           318: struct wait1_args {
1.1       root      319:                int     pid;
                    320:                int     *status;
                    321:                int     options;
                    322:                struct  rusage *rusage;
                    323: #ifdef COMPAT_43
                    324:                int compat;
                    325: #endif
1.1.1.4 ! root      326: };
        !           327: 
        !           328: int
        !           329: wait1(q, uap, retval)
        !           330:        register struct proc *q;
        !           331:        register struct wait1_args *uap;
1.1       root      332:        int retval[];
                    333: {
                    334:        register int nfound;
                    335:        register struct proc *p;
                    336:        int status, error;
                    337: 
                    338:        if (uap->pid == 0)
                    339:                uap->pid = -q->p_pgid;
                    340: #ifdef notyet
                    341:        if (uap->options &~ (WUNTRACED|WNOHANG))
                    342:                return (EINVAL);
                    343: #endif
                    344: loop:
                    345:        nfound = 0;
                    346:        for (p = q->p_cptr; p; p = p->p_osptr) {
                    347:                if (uap->pid != WAIT_ANY &&
                    348:                    p->p_pid != uap->pid && p->p_pgid != -uap->pid)
                    349:                        continue;
                    350:                nfound++;
                    351:                if (p->p_stat == SZOMB) {
                    352:                        retval[0] = p->p_pid;
                    353: #ifdef COMPAT_43
                    354:                        if (uap->compat)
                    355:                                retval[1] = p->p_xstat;
                    356:                        else
                    357: #endif
                    358:                        if (uap->status) {
                    359:                                status = p->p_xstat;    /* convert to int */
                    360:                                if (error = copyout((caddr_t)&status,
                    361:                                    (caddr_t)uap->status, sizeof(status)))
                    362:                                        return (error);
                    363:                        }
                    364:                        if (uap->rusage && (error = copyout((caddr_t)p->p_ru,
                    365:                            (caddr_t)uap->rusage, sizeof (struct rusage))))
                    366:                                return (error);
                    367:                        p->p_xstat = 0;
                    368:                        ruadd(&q->p_stats->p_cru, p->p_ru);
                    369:                        FREE(p->p_ru, M_ZOMBIE);
                    370:                        if (--p->p_cred->p_refcnt == 0) {
                    371:                                crfree(p->p_cred->pc_ucred);
                    372:                                FREE(p->p_cred, M_SUBPROC);
1.1.1.2   root      373:                                p->p_cred = (struct pcred *) -1;
1.1       root      374:                        }
                    375: 
                    376:                        /*
                    377:                         * Finally finished with old proc entry.
                    378:                         * Unlink it from its process group and free it.
                    379:                         */
                    380:                        leavepgrp(p);
                    381:                        if (*p->p_prev = p->p_nxt)      /* off zombproc */
                    382:                                p->p_nxt->p_prev = p->p_prev;
                    383:                        if (q = p->p_ysptr)
                    384:                                q->p_osptr = p->p_osptr;
                    385:                        if (q = p->p_osptr)
                    386:                                q->p_ysptr = p->p_ysptr;
                    387:                        if ((q = p->p_pptr)->p_cptr == p)
                    388:                                q->p_cptr = p->p_osptr;
                    389: 
                    390:                        /*
                    391:                         * Give machine-dependent layer a chance
                    392:                         * to free anything that cpu_exit couldn't
                    393:                         * release while still running in process context.
                    394:                         */
                    395:                        cpu_wait(p);
                    396:                        FREE(p, M_PROC);
                    397:                        nprocs--;
                    398:                        return (0);
                    399:                }
                    400:                if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 &&
                    401:                    (p->p_flag & STRC || uap->options & WUNTRACED)) {
                    402:                        p->p_flag |= SWTED;
                    403:                        retval[0] = p->p_pid;
                    404: #ifdef COMPAT_43
                    405:                        if (uap->compat) {
                    406:                                retval[1] = W_STOPCODE(p->p_xstat);
                    407:                                error = 0;
                    408:                        } else
                    409: #endif
                    410:                        if (uap->status) {
                    411:                                status = W_STOPCODE(p->p_xstat);
                    412:                                error = copyout((caddr_t)&status,
                    413:                                    (caddr_t)uap->status, sizeof(status));
                    414:                        } else
                    415:                                error = 0;
                    416:                        return (error);
                    417:                }
                    418:        }
                    419:        if (nfound == 0)
                    420:                return (ECHILD);
                    421:        if (uap->options & WNOHANG) {
                    422:                retval[0] = 0;
                    423:                return (0);
                    424:        }
                    425:        if (error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0))
                    426:                return (error);
                    427:        goto loop;
                    428: }

unix.superglobalmegacorp.com

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