[BACK]Return to kern_exit.c CVS log [TXT][DIR] Up to [local] / sys / kern

Annotation of sys/kern/kern_exit.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: kern_exit.c,v 1.71 2007/04/12 22:14:15 tedu Exp $     */
        !             2: /*     $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $  */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1982, 1986, 1989, 1991, 1993
        !             6:  *     The Regents of the University of California.  All rights reserved.
        !             7:  * (c) UNIX System Laboratories, Inc.
        !             8:  * All or some portions of this file are derived from material licensed
        !             9:  * to the University of California by American Telephone and Telegraph
        !            10:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
        !            11:  * the permission of UNIX System Laboratories, Inc.
        !            12:  *
        !            13:  * Redistribution and use in source and binary forms, with or without
        !            14:  * modification, are permitted provided that the following conditions
        !            15:  * are met:
        !            16:  * 1. Redistributions of source code must retain the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer.
        !            18:  * 2. Redistributions in binary form must reproduce the above copyright
        !            19:  *    notice, this list of conditions and the following disclaimer in the
        !            20:  *    documentation and/or other materials provided with the distribution.
        !            21:  * 3. Neither the name of the University nor the names of its contributors
        !            22:  *    may be used to endorse or promote products derived from this software
        !            23:  *    without specific prior written permission.
        !            24:  *
        !            25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            35:  * SUCH DAMAGE.
        !            36:  *
        !            37:  *     @(#)kern_exit.c 8.7 (Berkeley) 2/12/94
        !            38:  */
        !            39:
        !            40: #include <sys/param.h>
        !            41: #include <sys/systm.h>
        !            42: #include <sys/ioctl.h>
        !            43: #include <sys/proc.h>
        !            44: #include <sys/tty.h>
        !            45: #include <sys/time.h>
        !            46: #include <sys/resource.h>
        !            47: #include <sys/kernel.h>
        !            48: #include <sys/buf.h>
        !            49: #include <sys/wait.h>
        !            50: #include <sys/file.h>
        !            51: #include <sys/vnode.h>
        !            52: #include <sys/syslog.h>
        !            53: #include <sys/malloc.h>
        !            54: #include <sys/resourcevar.h>
        !            55: #include <sys/ptrace.h>
        !            56: #include <sys/acct.h>
        !            57: #include <sys/filedesc.h>
        !            58: #include <sys/signalvar.h>
        !            59: #include <sys/sched.h>
        !            60: #include <sys/ktrace.h>
        !            61: #include <sys/pool.h>
        !            62: #include <sys/mutex.h>
        !            63: #ifdef SYSVSHM
        !            64: #include <sys/shm.h>
        !            65: #endif
        !            66: #ifdef SYSVSEM
        !            67: #include <sys/sem.h>
        !            68: #endif
        !            69:
        !            70: #include "systrace.h"
        !            71: #include <dev/systrace.h>
        !            72:
        !            73: #include <sys/mount.h>
        !            74: #include <sys/syscallargs.h>
        !            75:
        !            76: #include <machine/cpu.h>
        !            77:
        !            78: #include <uvm/uvm_extern.h>
        !            79:
        !            80: /*
        !            81:  * exit --
        !            82:  *     Death of process.
        !            83:  */
        !            84: int
        !            85: sys_exit(struct proc *p, void *v, register_t *retval)
        !            86: {
        !            87:        struct sys_exit_args /* {
        !            88:                syscallarg(int) rval;
        !            89:        } */ *uap = v;
        !            90:
        !            91:        exit1(p, W_EXITCODE(SCARG(uap, rval), 0), EXIT_NORMAL);
        !            92:        /* NOTREACHED */
        !            93:        return (0);
        !            94: }
        !            95:
        !            96: #ifdef RTHREADS
        !            97: int
        !            98: sys_threxit(struct proc *p, void *v, register_t *retval)
        !            99: {
        !           100:        struct sys_threxit_args *uap = v;
        !           101:
        !           102:        exit1(p, W_EXITCODE(SCARG(uap, rval), 0), EXIT_THREAD);
        !           103:
        !           104:        return (0);
        !           105: }
        !           106: #endif
        !           107:
        !           108: /*
        !           109:  * Exit: deallocate address space and other resources, change proc state
        !           110:  * to zombie, and unlink proc from allproc and parent's lists.  Save exit
        !           111:  * status and rusage for wait().  Check for child processes and orphan them.
        !           112:  */
        !           113: void
        !           114: exit1(struct proc *p, int rv, int flags)
        !           115: {
        !           116:        struct proc *q, *nq;
        !           117:
        !           118:        if (p->p_pid == 1)
        !           119:                panic("init died (signal %d, exit %d)",
        !           120:                    WTERMSIG(rv), WEXITSTATUS(rv));
        !           121:
        !           122:        /* unlink ourselves from the active threads */
        !           123:        TAILQ_REMOVE(&p->p_p->ps_threads, p, p_thr_link);
        !           124: #ifdef RTHREADS
        !           125:        if (TAILQ_EMPTY(&p->p_p->ps_threads))
        !           126:                wakeup(&p->p_p->ps_threads);
        !           127:        /*
        !           128:         * if one thread calls exit, we take down everybody.
        !           129:         * we have to be careful not to get recursively caught.
        !           130:         * this is kinda sick.
        !           131:         */
        !           132:        if (flags == EXIT_NORMAL && p->p_p->ps_mainproc != p &&
        !           133:            (p->p_p->ps_mainproc->p_flag & P_WEXIT) == 0) {
        !           134:                /*
        !           135:                 * we are one of the threads.  we SIGKILL the parent,
        !           136:                 * it will wake us up again, then we proceed.
        !           137:                 */
        !           138:                atomic_setbits_int(&p->p_p->ps_mainproc->p_flag, P_IGNEXITRV);
        !           139:                p->p_p->ps_mainproc->p_xstat = rv;
        !           140:                psignal(p->p_p->ps_mainproc, SIGKILL);
        !           141:                tsleep(p->p_p, PUSER, "thrdying", 0);
        !           142:        } else if (p == p->p_p->ps_mainproc) {
        !           143:                atomic_setbits_int(&p->p_flag, P_WEXIT);
        !           144:                if (flags == EXIT_NORMAL) {
        !           145:                        q = TAILQ_FIRST(&p->p_p->ps_threads);
        !           146:                        for (; q != NULL; q = nq) {
        !           147:                                nq = TAILQ_NEXT(q, p_thr_link);
        !           148:                                atomic_setbits_int(&q->p_flag, P_IGNEXITRV);
        !           149:                                q->p_xstat = rv;
        !           150:                                psignal(q, SIGKILL);
        !           151:                        }
        !           152:                }
        !           153:                wakeup(p->p_p);
        !           154:                while (!TAILQ_EMPTY(&p->p_p->ps_threads))
        !           155:                        tsleep(&p->p_p->ps_threads, PUSER, "thrdeath", 0);
        !           156:        }
        !           157: #endif
        !           158:
        !           159:        if (p->p_flag & P_PROFIL)
        !           160:                stopprofclock(p);
        !           161:        p->p_ru = pool_get(&rusage_pool, PR_WAITOK);
        !           162:        /*
        !           163:         * If parent is waiting for us to exit or exec, P_PPWAIT is set; we
        !           164:         * wake up the parent early to avoid deadlock.
        !           165:         */
        !           166:        atomic_setbits_int(&p->p_flag, P_WEXIT);
        !           167:        atomic_clearbits_int(&p->p_flag, P_TRACED);
        !           168:        if (p->p_flag & P_PPWAIT) {
        !           169:                atomic_clearbits_int(&p->p_flag, P_PPWAIT);
        !           170:                wakeup(p->p_pptr);
        !           171:        }
        !           172:        p->p_sigignore = ~0;
        !           173:        p->p_siglist = 0;
        !           174:        timeout_del(&p->p_realit_to);
        !           175:        timeout_del(&p->p_stats->p_virt_to);
        !           176:        timeout_del(&p->p_stats->p_prof_to);
        !           177:
        !           178:        /*
        !           179:         * Close open files and release open-file table.
        !           180:         * This may block!
        !           181:         */
        !           182:        fdfree(p);
        !           183:
        !           184: #ifdef SYSVSEM
        !           185:        semexit(p);
        !           186: #endif
        !           187:        if (SESS_LEADER(p)) {
        !           188:                struct session *sp = p->p_session;
        !           189:
        !           190:                if (sp->s_ttyvp) {
        !           191:                        /*
        !           192:                         * Controlling process.
        !           193:                         * Signal foreground pgrp,
        !           194:                         * drain controlling terminal
        !           195:                         * and revoke access to controlling terminal.
        !           196:                         */
        !           197:                        if (sp->s_ttyp->t_session == sp) {
        !           198:                                if (sp->s_ttyp->t_pgrp)
        !           199:                                        pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
        !           200:                                (void) ttywait(sp->s_ttyp);
        !           201:                                /*
        !           202:                                 * The tty could have been revoked
        !           203:                                 * if we blocked.
        !           204:                                 */
        !           205:                                if (sp->s_ttyvp)
        !           206:                                        VOP_REVOKE(sp->s_ttyvp, REVOKEALL);
        !           207:                        }
        !           208:                        if (sp->s_ttyvp)
        !           209:                                vrele(sp->s_ttyvp);
        !           210:                        sp->s_ttyvp = NULL;
        !           211:                        /*
        !           212:                         * s_ttyp is not zero'd; we use this to indicate
        !           213:                         * that the session once had a controlling terminal.
        !           214:                         * (for logging and informational purposes)
        !           215:                         */
        !           216:                }
        !           217:                sp->s_leader = NULL;
        !           218:        }
        !           219:        fixjobc(p, p->p_pgrp, 0);
        !           220: #ifdef ACCOUNTING
        !           221:        (void)acct_process(p);
        !           222: #endif
        !           223: #ifdef KTRACE
        !           224:        /*
        !           225:         * release trace file
        !           226:         */
        !           227:        p->p_traceflag = 0;     /* don't trace the vrele() */
        !           228:        if (p->p_tracep)
        !           229:                ktrsettracevnode(p, NULL);
        !           230: #endif
        !           231: #if NSYSTRACE > 0
        !           232:        if (ISSET(p->p_flag, P_SYSTRACE))
        !           233:                systrace_exit(p);
        !           234: #endif
        !           235:        /*
        !           236:         * NOTE: WE ARE NO LONGER ALLOWED TO SLEEP!
        !           237:         */
        !           238:        p->p_stat = SDEAD;
        !           239:
        !           240:         /*
        !           241:          * Remove proc from pidhash chain so looking it up won't
        !           242:          * work.  Move it from allproc to zombproc, but do not yet
        !           243:          * wake up the reaper.  We will put the proc on the
        !           244:          * deadproc list later (using the p_hash member), and
        !           245:          * wake up the reaper when we do.
        !           246:          */
        !           247:        LIST_REMOVE(p, p_hash);
        !           248:        LIST_REMOVE(p, p_list);
        !           249:        LIST_INSERT_HEAD(&zombproc, p, p_list);
        !           250:
        !           251:        /*
        !           252:         * Give orphaned children to init(8).
        !           253:         */
        !           254:        q = LIST_FIRST(&p->p_children);
        !           255:        if (q)          /* only need this if any child is S_ZOMB */
        !           256:                wakeup(initproc);
        !           257:        for (; q != 0; q = nq) {
        !           258:                nq = LIST_NEXT(q, p_sibling);
        !           259:                proc_reparent(q, initproc);
        !           260:                /*
        !           261:                 * Traced processes are killed
        !           262:                 * since their existence means someone is screwing up.
        !           263:                 */
        !           264:                if (q->p_flag & P_TRACED) {
        !           265:                        atomic_clearbits_int(&q->p_flag, P_TRACED);
        !           266:                        psignal(q, SIGKILL);
        !           267:                }
        !           268:        }
        !           269:
        !           270:
        !           271:        /*
        !           272:         * Save exit status and final rusage info, adding in child rusage
        !           273:         * info and self times.
        !           274:         */
        !           275:        if (!(p->p_flag & P_IGNEXITRV))
        !           276:                p->p_xstat = rv;
        !           277:        *p->p_ru = p->p_stats->p_ru;
        !           278:        calcru(p, &p->p_ru->ru_utime, &p->p_ru->ru_stime, NULL);
        !           279:        ruadd(p->p_ru, &p->p_stats->p_cru);
        !           280:
        !           281:        /*
        !           282:         * clear %cpu usage during swap
        !           283:         */
        !           284:        p->p_pctcpu = 0;
        !           285:
        !           286:        /*
        !           287:         * notify interested parties of our demise.
        !           288:         */
        !           289:        KNOTE(&p->p_klist, NOTE_EXIT);
        !           290:
        !           291:        /*
        !           292:         * Notify parent that we're gone.  If we have P_NOZOMBIE or parent has
        !           293:         * the P_NOCLDWAIT flag set, notify process 1 instead (and hope it
        !           294:         * will handle this situation).
        !           295:         */
        !           296:        if ((p->p_flag & P_NOZOMBIE) || (p->p_pptr->p_flag & P_NOCLDWAIT)) {
        !           297:                struct proc *pp = p->p_pptr;
        !           298:                proc_reparent(p, initproc);
        !           299:                /*
        !           300:                 * If this was the last child of our parent, notify
        !           301:                 * parent, so in case he was wait(2)ing, he will
        !           302:                 * continue.
        !           303:                 */
        !           304:                if (LIST_EMPTY(&pp->p_children))
        !           305:                        wakeup(pp);
        !           306:        }
        !           307:
        !           308:        if (p->p_exitsig != 0)
        !           309:                psignal(p->p_pptr, P_EXITSIG(p));
        !           310:        wakeup(p->p_pptr);
        !           311:
        !           312:        /*
        !           313:         * Release the process's signal state.
        !           314:         */
        !           315:        sigactsfree(p);
        !           316:
        !           317:        /*
        !           318:         * Clear curproc after we've done all operations
        !           319:         * that could block, and before tearing down the rest
        !           320:         * of the process state that might be used from clock, etc.
        !           321:         * Also, can't clear curproc while we're still runnable,
        !           322:         * as we're not on a run queue (we are current, just not
        !           323:         * a proper proc any longer!).
        !           324:         *
        !           325:         * Other substructures are freed from wait().
        !           326:         */
        !           327:        curproc = NULL;
        !           328:
        !           329:        /*
        !           330:         * If emulation has process exit hook, call it now.
        !           331:         */
        !           332:        if (p->p_emul->e_proc_exit)
        !           333:                (*p->p_emul->e_proc_exit)(p);
        !           334:
        !           335:        /* This process no longer needs to hold the kernel lock. */
        !           336:        KERNEL_PROC_UNLOCK(p);
        !           337:
        !           338:        /*
        !           339:         * Finally, call machine-dependent code to switch to a new
        !           340:         * context (possibly the idle context).  Once we are no longer
        !           341:         * using the dead process's vmspace and stack, exit2() will be
        !           342:         * called to schedule those resources to be released by the
        !           343:         * reaper thread.
        !           344:         *
        !           345:         * Note that cpu_exit() will end with a call equivalent to
        !           346:         * cpu_switch(), finishing our execution (pun intended).
        !           347:         */
        !           348:        uvmexp.swtch++;
        !           349:        cpu_exit(p);
        !           350: }
        !           351:
        !           352: /*
        !           353:  * Locking of this proclist is special; it's accessed in a
        !           354:  * critical section of process exit, and thus locking it can't
        !           355:  * modify interrupt state.  We use a simple spin lock for this
        !           356:  * proclist.  Processes on this proclist are also on zombproc;
        !           357:  * we use the p_hash member to linkup to deadproc.
        !           358:  */
        !           359: struct mutex deadproc_mutex = MUTEX_INITIALIZER(IPL_NONE);
        !           360: struct proclist deadproc = LIST_HEAD_INITIALIZER(deadproc);
        !           361:
        !           362: /*
        !           363:  * We are called from cpu_exit() once it is safe to schedule the
        !           364:  * dead process's resources to be freed.
        !           365:  *
        !           366:  * NOTE: One must be careful with locking in this routine.  It's
        !           367:  * called from a critical section in machine-dependent code, so
        !           368:  * we should refrain from changing any interrupt state.
        !           369:  *
        !           370:  * We lock the deadproc list, place the proc on that list (using
        !           371:  * the p_hash member), and wake up the reaper.
        !           372:  */
        !           373: void
        !           374: exit2(struct proc *p)
        !           375: {
        !           376:        int s;
        !           377:
        !           378:        mtx_enter(&deadproc_mutex);
        !           379:        LIST_INSERT_HEAD(&deadproc, p, p_hash);
        !           380:        mtx_leave(&deadproc_mutex);
        !           381:
        !           382:        wakeup(&deadproc);
        !           383:
        !           384:        SCHED_LOCK(s);
        !           385: }
        !           386:
        !           387: /*
        !           388:  * Process reaper.  This is run by a kernel thread to free the resources
        !           389:  * of a dead process.  Once the resources are free, the process becomes
        !           390:  * a zombie, and the parent is allowed to read the undead's status.
        !           391:  */
        !           392: void
        !           393: reaper(void)
        !           394: {
        !           395:        struct proc *p;
        !           396:
        !           397:        KERNEL_PROC_UNLOCK(curproc);
        !           398:
        !           399:        for (;;) {
        !           400:                mtx_enter(&deadproc_mutex);
        !           401:                p = LIST_FIRST(&deadproc);
        !           402:                if (p == NULL) {
        !           403:                        /* No work for us; go to sleep until someone exits. */
        !           404:                        mtx_leave(&deadproc_mutex);
        !           405:                        (void) tsleep(&deadproc, PVM, "reaper", 0);
        !           406:                        continue;
        !           407:                }
        !           408:
        !           409:                /* Remove us from the deadproc list. */
        !           410:                LIST_REMOVE(p, p_hash);
        !           411:                mtx_leave(&deadproc_mutex);
        !           412:                KERNEL_PROC_LOCK(curproc);
        !           413:
        !           414:                /*
        !           415:                 * Give machine-dependent code a chance to free any
        !           416:                 * resources it couldn't free while still running on
        !           417:                 * that process's context.  This must be done before
        !           418:                 * uvm_exit(), in case these resources are in the PCB.
        !           419:                 */
        !           420:                cpu_wait(p);
        !           421:
        !           422:                /*
        !           423:                 * Free the VM resources we're still holding on to.
        !           424:                 * We must do this from a valid thread because doing
        !           425:                 * so may block.
        !           426:                 */
        !           427:                uvm_exit(p);
        !           428:
        !           429:                /* Process is now a true zombie. */
        !           430:                if ((p->p_flag & P_NOZOMBIE) == 0) {
        !           431:                        p->p_stat = SZOMB;
        !           432:
        !           433:                        /* Wake up the parent so it can get exit status. */
        !           434:                        psignal(p->p_pptr, SIGCHLD);
        !           435:                        wakeup(p->p_pptr);
        !           436:                } else {
        !           437:                        /* Noone will wait for us. Just zap the process now */
        !           438:                        proc_zap(p);
        !           439:                }
        !           440:
        !           441:                KERNEL_PROC_UNLOCK(curproc);
        !           442:        }
        !           443: }
        !           444:
        !           445: pid_t
        !           446: sys_wait4(struct proc *q, void *v, register_t *retval)
        !           447: {
        !           448:        struct sys_wait4_args /* {
        !           449:                syscallarg(pid_t) pid;
        !           450:                syscallarg(int *) status;
        !           451:                syscallarg(int) options;
        !           452:                syscallarg(struct rusage *) rusage;
        !           453:        } */ *uap = v;
        !           454:        int nfound;
        !           455:        struct proc *p, *t;
        !           456:        int status, error;
        !           457:
        !           458:        if (SCARG(uap, pid) == 0)
        !           459:                SCARG(uap, pid) = -q->p_pgid;
        !           460:        if (SCARG(uap, options) &~ (WUNTRACED|WNOHANG|WALTSIG|WCONTINUED))
        !           461:                return (EINVAL);
        !           462:
        !           463: loop:
        !           464:        nfound = 0;
        !           465:        LIST_FOREACH(p, &q->p_children, p_sibling) {
        !           466:                if ((p->p_flag & P_NOZOMBIE) ||
        !           467:                    (SCARG(uap, pid) != WAIT_ANY &&
        !           468:                    p->p_pid != SCARG(uap, pid) &&
        !           469:                    p->p_pgid != -SCARG(uap, pid)))
        !           470:                        continue;
        !           471:
        !           472:                /*
        !           473:                 * Wait for processes with p_exitsig != SIGCHLD processes only
        !           474:                 * if WALTSIG is set; wait for processes with pexitsig ==
        !           475:                 * SIGCHLD only if WALTSIG is clear.
        !           476:                 */
        !           477:                if ((SCARG(uap, options) & WALTSIG) ?
        !           478:                    (p->p_exitsig == SIGCHLD) : (P_EXITSIG(p) != SIGCHLD))
        !           479:                        continue;
        !           480:
        !           481:                nfound++;
        !           482:                if (p->p_stat == SZOMB) {
        !           483:                        retval[0] = p->p_pid;
        !           484:
        !           485:                        if (SCARG(uap, status)) {
        !           486:                                status = p->p_xstat;    /* convert to int */
        !           487:                                error = copyout(&status,
        !           488:                                    SCARG(uap, status), sizeof(status));
        !           489:                                if (error)
        !           490:                                        return (error);
        !           491:                        }
        !           492:                        if (SCARG(uap, rusage) &&
        !           493:                            (error = copyout(p->p_ru,
        !           494:                            SCARG(uap, rusage), sizeof(struct rusage))))
        !           495:                                return (error);
        !           496:
        !           497:                        /*
        !           498:                         * If we got the child via a ptrace 'attach',
        !           499:                         * we need to give it back to the old parent.
        !           500:                         */
        !           501:                        if (p->p_oppid && (t = pfind(p->p_oppid))) {
        !           502:                                p->p_oppid = 0;
        !           503:                                proc_reparent(p, t);
        !           504:                                if (p->p_exitsig != 0)
        !           505:                                        psignal(t, P_EXITSIG(p));
        !           506:                                wakeup(t);
        !           507:                                return (0);
        !           508:                        }
        !           509:
        !           510:                        scheduler_wait_hook(q, p);
        !           511:                        p->p_xstat = 0;
        !           512:                        ruadd(&q->p_stats->p_cru, p->p_ru);
        !           513:
        !           514:                        proc_zap(p);
        !           515:
        !           516:                        return (0);
        !           517:                }
        !           518:                if (p->p_stat == SSTOP && (p->p_flag & P_WAITED) == 0 &&
        !           519:                    (p->p_flag & P_TRACED || SCARG(uap, options) & WUNTRACED)) {
        !           520:                        atomic_setbits_int(&p->p_flag, P_WAITED);
        !           521:                        retval[0] = p->p_pid;
        !           522:
        !           523:                        if (SCARG(uap, status)) {
        !           524:                                status = W_STOPCODE(p->p_xstat);
        !           525:                                error = copyout(&status, SCARG(uap, status),
        !           526:                                    sizeof(status));
        !           527:                        } else
        !           528:                                error = 0;
        !           529:                        return (error);
        !           530:                }
        !           531:                if ((SCARG(uap, options) & WCONTINUED) && (p->p_flag & P_CONTINUED)) {
        !           532:                        atomic_clearbits_int(&p->p_flag, P_CONTINUED);
        !           533:                        retval[0] = p->p_pid;
        !           534:
        !           535:                        if (SCARG(uap, status)) {
        !           536:                                status = _WCONTINUED;
        !           537:                                error = copyout(&status, SCARG(uap, status),
        !           538:                                    sizeof(status));
        !           539:                        } else
        !           540:                                error = 0;
        !           541:                        return (error);
        !           542:                }
        !           543:        }
        !           544:        if (nfound == 0)
        !           545:                return (ECHILD);
        !           546:        if (SCARG(uap, options) & WNOHANG) {
        !           547:                retval[0] = 0;
        !           548:                return (0);
        !           549:        }
        !           550:        if ((error = tsleep(q, PWAIT | PCATCH, "wait", 0)) != 0)
        !           551:                return (error);
        !           552:        goto loop;
        !           553: }
        !           554:
        !           555: /*
        !           556:  * make process 'parent' the new parent of process 'child'.
        !           557:  */
        !           558: void
        !           559: proc_reparent(struct proc *child, struct proc *parent)
        !           560: {
        !           561:
        !           562:        if (child->p_pptr == parent)
        !           563:                return;
        !           564:
        !           565:        if (parent == initproc)
        !           566:                child->p_exitsig = SIGCHLD;
        !           567:
        !           568:        LIST_REMOVE(child, p_sibling);
        !           569:        LIST_INSERT_HEAD(&parent->p_children, child, p_sibling);
        !           570:        child->p_pptr = parent;
        !           571: }
        !           572:
        !           573: void
        !           574: proc_zap(struct proc *p)
        !           575: {
        !           576:        pool_put(&rusage_pool, p->p_ru);
        !           577:        if (p->p_ptstat)
        !           578:                free(p->p_ptstat, M_SUBPROC);
        !           579:
        !           580:        /*
        !           581:         * Finally finished with old proc entry.
        !           582:         * Unlink it from its process group and free it.
        !           583:         */
        !           584:        leavepgrp(p);
        !           585:        LIST_REMOVE(p, p_list); /* off zombproc */
        !           586:        LIST_REMOVE(p, p_sibling);
        !           587:
        !           588:        /*
        !           589:         * Decrement the count of procs running with this uid.
        !           590:         */
        !           591:        (void)chgproccnt(p->p_cred->p_ruid, -1);
        !           592:
        !           593:        /*
        !           594:         * Release reference to text vnode
        !           595:         */
        !           596:        if (p->p_textvp)
        !           597:                vrele(p->p_textvp);
        !           598:
        !           599:        /*
        !           600:         * Remove us from our process list, possibly killing the process
        !           601:         * in the process (pun intended).
        !           602:         */
        !           603: #if 0
        !           604:        TAILQ_REMOVE(&p->p_p->ps_threads, p, p_thr_link);
        !           605: #endif
        !           606:        if (TAILQ_EMPTY(&p->p_p->ps_threads)) {
        !           607:                limfree(p->p_p->ps_limit);
        !           608:                if (--p->p_p->ps_cred->p_refcnt == 0) {
        !           609:                        crfree(p->p_p->ps_cred->pc_ucred);
        !           610:                        pool_put(&pcred_pool, p->p_p->ps_cred);
        !           611:                }
        !           612:                pool_put(&process_pool, p->p_p);
        !           613:        }
        !           614:
        !           615:        pool_put(&proc_pool, p);
        !           616:        nprocs--;
        !           617: }
        !           618:

CVSweb