Annotation of XNU/bsd/kern/kern_exit.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */
        !            23: /*
        !            24:  * Copyright (c) 1982, 1986, 1989, 1991, 1993
        !            25:  *     The Regents of the University of California.  All rights reserved.
        !            26:  * (c) UNIX System Laboratories, Inc.
        !            27:  * All or some portions of this file are derived from material licensed
        !            28:  * to the University of California by American Telephone and Telegraph
        !            29:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
        !            30:  * the permission of UNIX System Laboratories, Inc.
        !            31:  *
        !            32:  * Redistribution and use in source and binary forms, with or without
        !            33:  * modification, are permitted provided that the following conditions
        !            34:  * are met:
        !            35:  * 1. Redistributions of source code must retain the above copyright
        !            36:  *    notice, this list of conditions and the following disclaimer.
        !            37:  * 2. Redistributions in binary form must reproduce the above copyright
        !            38:  *    notice, this list of conditions and the following disclaimer in the
        !            39:  *    documentation and/or other materials provided with the distribution.
        !            40:  * 3. All advertising materials mentioning features or use of this software
        !            41:  *    must display the following acknowledgement:
        !            42:  *     This product includes software developed by the University of
        !            43:  *     California, Berkeley and its contributors.
        !            44:  * 4. Neither the name of the University nor the names of its contributors
        !            45:  *    may be used to endorse or promote products derived from this software
        !            46:  *    without specific prior written permission.
        !            47:  *
        !            48:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            49:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            50:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            51:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            52:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            53:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            54:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            55:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            56:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            57:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            58:  * SUCH DAMAGE.
        !            59:  *
        !            60:  *     @(#)kern_exit.c 8.7 (Berkeley) 2/12/94
        !            61:  */
        !            62:  
        !            63: #include <machine/reg.h>
        !            64: #include <machine/psl.h>
        !            65: 
        !            66: #include "compat_43.h"
        !            67: 
        !            68: #include <sys/param.h>
        !            69: #include <sys/systm.h>
        !            70: #include <sys/ioctl.h>
        !            71: #include <sys/proc.h>
        !            72: #include <sys/tty.h>
        !            73: #include <sys/time.h>
        !            74: #include <sys/resource.h>
        !            75: #include <sys/kernel.h>
        !            76: #include <sys/buf.h>
        !            77: #include <sys/wait.h>
        !            78: #include <sys/file.h>
        !            79: #include <sys/vnode.h>
        !            80: #include <sys/syslog.h>
        !            81: #include <sys/malloc.h>
        !            82: #include <sys/resourcevar.h>
        !            83: #include <sys/ptrace.h>
        !            84: #include <sys/user.h>
        !            85: 
        !            86: #include <mach/mach_types.h>
        !            87: #include <kern/thread.h>
        !            88: #include <kern/thread_act.h>
        !            89: #include <kern/assert.h>
        !            90: 
        !            91: void exit1 __P((struct proc *, int));
        !            92: 
        !            93: /*
        !            94:  * exit --
        !            95:  *     Death of process.
        !            96:  */
        !            97: struct exit_args {
        !            98:        int     rval;
        !            99: };
        !           100: void
        !           101: exit(p, uap, retval)
        !           102:        struct proc *p;
        !           103:        struct exit_args *uap;
        !           104:        int *retval;
        !           105: {
        !           106:        exit1(p, W_EXITCODE(uap->rval, 0));
        !           107: 
        !           108:        thread_exception_return();
        !           109:        /* NOTREACHED */
        !           110:        while (TRUE)
        !           111:                thread_block(0);
        !           112:        /* NOTREACHED */
        !           113: }
        !           114: 
        !           115: /*
        !           116:  * Exit: deallocate address space and other resources, change proc state
        !           117:  * to zombie, and unlink proc from allproc and parent's lists.  Save exit
        !           118:  * status and rusage for wait().  Check for child processes and orphan them.
        !           119:  */
        !           120: void
        !           121: exit1(p, rv)
        !           122:        register struct proc *p;
        !           123:        int rv;
        !           124: {
        !           125:        register struct proc *q, *nq;
        !           126:        thread_t self = current_thread();
        !           127:        thread_act_t th_act_self = current_act();
        !           128:        struct task *task = p->task;
        !           129:        register int i,s;
        !           130:        struct uthread *ut;
        !           131: 
        !           132:        /*
        !           133:         * If a thread in this task has already
        !           134:         * called exit(), then halt any others
        !           135:         * right here.
        !           136:         */
        !           137:        while (p->exit_thread != self) {
        !           138:                if (sig_try_lock(p) <= 0) {
        !           139:                        if (get_threadtask(th_act_self) != task)
        !           140:                                return;
        !           141:                        while (TRUE) {
        !           142:                                thread_terminate_self();
        !           143:                                /* NOTREACHED */
        !           144:                        }
        !           145:                }
        !           146:                sig_lock_to_exit(p);
        !           147:        }
        !           148:        if (p->p_pid == 1) {
        !           149:                printf("pid 1 exited (signal %d, exit %d)",
        !           150:                    WTERMSIG(rv), WEXITSTATUS(rv));
        !           151:                panic("init died");
        !           152:        }
        !           153: 
        !           154:        s = splsched();
        !           155:        p->p_flag |= P_WEXIT;
        !           156:        splx(s);
        !           157:        proc_prepareexit(p);
        !           158:        p->p_xstat = rv;
        !           159: 
        !           160:        /* task terminate will call proc_terminate and that cleans it up */
        !           161:        task_terminate_internal(task);
        !           162: 
        !           163:        /*
        !           164:         * we come back and returns to AST which 
        !           165:         * should cleanup the rest 
        !           166:         */
        !           167: #if 0
        !           168:        if (task == current_task()) {
        !           169:                thread_exception_return();
        !           170:                /*NOTREACHED*/
        !           171:        }
        !           172: 
        !           173:        while (task == current_task()) {
        !           174:                thread_terminate_self();
        !           175:                /*NOTREACHED*/
        !           176:        }
        !           177: #endif
        !           178: }
        !           179: 
        !           180: void
        !           181: proc_prepareexit(struct proc *p) 
        !           182: {
        !           183:        int s;
        !           184:        struct uthread *ut;
        !           185:        thread_t self = current_thread();
        !           186:        thread_act_t th_act_self = current_act();
        !           187: 
        !           188: 
        !           189:        /*
        !           190:         * Remove proc from allproc queue and from pidhash chain.
        !           191:         * Need to do this before we do anything that can block.
        !           192:         * Not doing causes things like mount() find this on allproc
        !           193:         * in partially cleaned state.
        !           194:         */
        !           195:        LIST_REMOVE(p, p_list);
        !           196:        LIST_REMOVE(p, p_hash);
        !           197: 
        !           198: #ifdef PGINPROF
        !           199:        vmsizmon();
        !           200: #endif
        !           201:        /*
        !           202:         * If parent is waiting for us to exit or exec,
        !           203:         * P_PPWAIT is set; we will wakeup the parent below.
        !           204:         */
        !           205:        p->p_flag &= ~(P_TRACED | P_PPWAIT);
        !           206:        p->p_sigignore = ~0;
        !           207:        p->p_siglist = 0;
        !           208:        ut = get_bsdthread_info(th_act_self);
        !           209:        ut->uu_sig = 0;
        !           210:        untimeout(realitexpire, (caddr_t)p);
        !           211: 
        !           212: }
        !           213: 
        !           214: void 
        !           215: proc_exit(struct proc *p)
        !           216: {
        !           217:        register struct proc *q, *nq;
        !           218:        thread_t self = current_thread();
        !           219:        thread_act_t th_act_self = current_act();
        !           220:        struct task *task = p->task;
        !           221:        register int i,s;
        !           222:        struct uthread *ut;
        !           223:        boolean_t funnel_state;
        !           224: 
        !           225:        /* This can happen if thread_terminate of the single thread
        !           226:         * process 
        !           227:         */
        !           228: 
        !           229:        funnel_state = thread_set_funneled(TRUE);
        !           230:        if( !(p->p_flag & P_WEXIT)) {
        !           231:                s = splsched();
        !           232:                p->p_flag |= P_WEXIT;
        !           233:                splx(s);
        !           234:                proc_prepareexit(p);    
        !           235:        }
        !           236: 
        !           237:        MALLOC_ZONE(p->p_ru, struct rusage *,
        !           238:                        sizeof (*p->p_ru), M_ZOMBIE, M_WAITOK);
        !           239: 
        !           240:        /*
        !           241:         * Close open files and release open-file table.
        !           242:         * This may block!
        !           243:         */
        !           244:        fdfree(p);
        !           245: 
        !           246:        /* Close ref SYSV Shared memory*/
        !           247:        if (p->vm_shm)
        !           248:                shmexit(p);
        !           249:        
        !           250:        if (SESS_LEADER(p)) {
        !           251:                register struct session *sp = p->p_session;
        !           252: 
        !           253:                if (sp->s_ttyvp) {
        !           254:                        /*
        !           255:                         * Controlling process.
        !           256:                         * Signal foreground pgrp,
        !           257:                         * drain controlling terminal
        !           258:                         * and revoke access to controlling terminal.
        !           259:                         */
        !           260:                        if (sp->s_ttyp->t_session == sp) {
        !           261:                                if (sp->s_ttyp->t_pgrp)
        !           262:                                        pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
        !           263:                                (void) ttywait(sp->s_ttyp);
        !           264:                                /*
        !           265:                                 * The tty could have been revoked
        !           266:                                 * if we blocked.
        !           267:                                 */
        !           268:                                if (sp->s_ttyvp)
        !           269:                                        VOP_REVOKE(sp->s_ttyvp, REVOKEALL);
        !           270:                        }
        !           271:                        if (sp->s_ttyvp)
        !           272:                                vrele(sp->s_ttyvp);
        !           273:                        sp->s_ttyvp = NULL;
        !           274:                        /*
        !           275:                         * s_ttyp is not zero'd; we use this to indicate
        !           276:                         * that the session once had a controlling terminal.
        !           277:                         * (for logging and informational purposes)
        !           278:                         */
        !           279:                }
        !           280:                sp->s_leader = NULL;
        !           281:        }
        !           282: 
        !           283:        fixjobc(p, p->p_pgrp, 0);
        !           284:        p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
        !           285: #if KTRACE
        !           286:        /* 
        !           287:         * release trace file
        !           288:         */
        !           289:        p->p_traceflag = 0;     /* don't trace the vrele() */
        !           290:        if (p->p_tracep)
        !           291:                vrele(p->p_tracep);
        !           292: #endif
        !           293: 
        !           294: 
        !           295:        q = p->p_children.lh_first;
        !           296:        if (q)          /* only need this if any child is S_ZOMB */
        !           297:                wakeup((caddr_t) initproc);
        !           298:        for (; q != 0; q = nq) {
        !           299:                nq = q->p_sibling.le_next;
        !           300:                proc_reparent(q, initproc);
        !           301:                /*
        !           302:                 * Traced processes are killed
        !           303:                 * since their existence means someone is messing up.
        !           304:                 */
        !           305:                if (q->p_flag & P_TRACED) {
        !           306:                        q->p_flag &= ~P_TRACED;
        !           307:                        if (q->sigwait_thread) {
        !           308:                                thread_t sig_shuttle  = getshuttle_thread(q->sigwait_thread);
        !           309:                                /*
        !           310:                                 * The sigwait_thread could be stopped at a
        !           311:                                 * breakpoint. Wake it up to kill.
        !           312:                                 * Need to do this as it could be a thread which is not
        !           313:                                 * the first thread in the task. So any attempts to kill
        !           314:                                 * the process would result into a deadlock on q->sigwait.
        !           315:                                 */
        !           316:                                thread_resume((struct thread *)q->sigwait_thread);
        !           317:                                clear_wait(sig_shuttle, THREAD_INTERRUPTED, FALSE);
        !           318:                                threadsignal(q->sigwait_thread, SIGKILL, 0);
        !           319:                        }
        !           320:                        psignal(q, SIGKILL);
        !           321:                }
        !           322:        }
        !           323: 
        !           324: 
        !           325:        /*
        !           326:         * Save exit status and final rusage info, adding in child rusage
        !           327:         * info and self times.
        !           328:         */
        !           329:        *p->p_ru = p->p_stats->p_ru;
        !           330: 
        !           331:        timerclear(&p->p_ru->ru_utime);
        !           332:        timerclear(&p->p_ru->ru_stime);
        !           333: 
        !           334:        if (task) {
        !           335:                task_basic_info_data_t tinfo;
        !           336:                int task_info_stuff     = TASK_BASIC_INFO_COUNT;
        !           337: 
        !           338:                task_info(task, TASK_BASIC_INFO,&tinfo, &task_info_stuff);
        !           339:                p->p_ru->ru_utime.tv_sec = tinfo.user_time.seconds;
        !           340:                p->p_ru->ru_utime.tv_usec = tinfo.user_time.microseconds;
        !           341:                p->p_ru->ru_stime.tv_sec = tinfo.system_time.seconds;
        !           342:                p->p_ru->ru_stime.tv_usec = tinfo.system_time.microseconds;
        !           343:        }
        !           344: 
        !           345: 
        !           346:        ruadd(p->p_ru, &p->p_stats->p_cru);
        !           347: 
        !           348:        /*
        !           349:         * Free up profiling buffers.
        !           350:         */
        !           351:        {
        !           352:                struct uprof *p0 = &p->p_stats->p_prof, *p1, *pn;
        !           353: 
        !           354:                p1 = p0->pr_next;
        !           355:                p0->pr_next = NULL;
        !           356:                p0->pr_scale = 0;
        !           357: 
        !           358:                for (; p1 != NULL; p1 = pn) {
        !           359:                        pn = p1->pr_next;
        !           360:                        kfree((vm_offset_t)p1, sizeof *p1);
        !           361:                }
        !           362:        }
        !           363: 
        !           364: 
        !           365:        /* Place onto zombproc. */
        !           366:        LIST_INSERT_HEAD(&zombproc, p, p_list);
        !           367:        p->p_stat = SZOMB;
        !           368: 
        !           369:        /*
        !           370:         * Notify parent that we're gone.
        !           371:         */
        !           372:        psignal(p->p_pptr, SIGCHLD);
        !           373:        wakeup((caddr_t)p->p_pptr);
        !           374: 
        !           375:        /*
        !           376:         * Notify procfs debugger
        !           377:         */
        !           378:        if (p->p_flag & P_FSTRACE)
        !           379:                wakeup((caddr_t)p);
        !           380: 
        !           381:        /*
        !           382:         * Other substructures are freed from wait().
        !           383:         */
        !           384:        FREE_ZONE(p->p_stats, sizeof *p->p_stats, M_SUBPROC);
        !           385:        p->p_stats = NULL;
        !           386: 
        !           387:        FREE_ZONE(p->p_sigacts, sizeof *p->p_sigacts, M_SUBPROC);
        !           388:        p->p_sigacts = NULL;
        !           389: 
        !           390:        if (--p->p_limit->p_refcnt == 0)
        !           391:                FREE_ZONE(p->p_limit, sizeof *p->p_limit, M_SUBPROC);
        !           392:        p->p_limit = NULL;
        !           393: 
        !           394:        /*
        !           395:         * Finish up by terminating the task
        !           396:         * and halt this thread (only if a
        !           397:         * member of the task exiting).
        !           398:         */
        !           399:        p->task = TASK_NULL;
        !           400:        //task->proc = NULL;
        !           401:        set_bsdtask_info(task, NULL);
        !           402: 
        !           403:        (void) thread_set_funneled(funnel_state);
        !           404: }
        !           405: 
        !           406: 
        !           407: struct wait4_args {
        !           408:        int     pid;
        !           409:        int *status;
        !           410:        int options;
        !           411:        struct rusage *rusage;
        !           412: };
        !           413: 
        !           414: #if COMPAT_43
        !           415: int
        !           416: owait(p, uap, retval)
        !           417:        struct proc *p;
        !           418:        void *uap;
        !           419:        int *retval;
        !           420: {
        !           421:        struct wait4_args *a;
        !           422: 
        !           423:        a = (struct wait4_args *)get_bsduthreadarg(current_act());
        !           424: 
        !           425:        a->options = 0;
        !           426:        a->rusage = NULL;
        !           427:        a->pid = WAIT_ANY;
        !           428:        a->status = NULL;
        !           429:        return (wait1(p, a, retval, 1));
        !           430: }
        !           431: 
        !           432: int
        !           433: wait4(p, uap, retval)
        !           434:        struct proc *p;
        !           435:        struct wait4_args *uap;
        !           436:        int *retval;
        !           437: {
        !           438: 
        !           439:        return (wait1(p, uap, retval, 0));
        !           440: }
        !           441: 
        !           442: struct owait3_args {
        !           443:        int *status;
        !           444:        int options;
        !           445:        struct rusage *rusage;
        !           446: };
        !           447: 
        !           448: int
        !           449: owait3(p, uap, retval)
        !           450:        struct proc *p;
        !           451:        struct owait3_args *uap;
        !           452:        int *retval;
        !           453: {
        !           454:        struct wait4_args *a;
        !           455: 
        !           456:        a = (struct wait4_args *)get_bsduthreadarg(current_act);
        !           457: 
        !           458:        a->rusage = uap->rusage;
        !           459:        a->options = uap->options;
        !           460:        a->status = uap->status;
        !           461:        a->pid = WAIT_ANY;
        !           462: 
        !           463:        return (wait1(p, a, retval, 1));
        !           464: }
        !           465: 
        !           466: #else
        !           467: #define        wait1   wait4
        !           468: #endif
        !           469: 
        !           470: int
        !           471: wait1continue(result)
        !           472: {
        !           473:   void * p, *vt;
        !           474:   thread_act_t thread;
        !           475:   struct uthread *ut;
        !           476:   int *retval;
        !           477: 
        !           478:        if (result != 0) {
        !           479:          return(result);
        !           480:        }
        !           481: 
        !           482:     thread = current_act();
        !           483:        p = get_bsdtask_info(current_task());
        !           484:        ut = get_bsdthread_info(thread);
        !           485:        vt = get_bsduthreadarg(thread);
        !           486:        retval = get_bsduthreadrval(thread);
        !           487:        wait1((struct proc *)p, (struct wait4_args *)vt, retval, 0);
        !           488: }
        !           489: 
        !           490: int
        !           491: wait1(q, uap, retval, compat)
        !           492:        register struct proc *q;
        !           493:        register struct wait4_args *uap;
        !           494:        register_t *retval;
        !           495: #if COMPAT_43
        !           496:        int compat;
        !           497: #endif
        !           498: {
        !           499:        register int nfound;
        !           500:        register struct proc *p, *t;
        !           501:        int status, error;
        !           502: 
        !           503:        if (uap->pid == 0)
        !           504:                uap->pid = -q->p_pgid;
        !           505: 
        !           506: loop:
        !           507:        nfound = 0;
        !           508:        for (p = q->p_children.lh_first; p != 0; p = p->p_sibling.le_next) {
        !           509:                if (uap->pid != WAIT_ANY &&
        !           510:                    p->p_pid != uap->pid &&
        !           511:                    p->p_pgid != -(uap->pid))
        !           512:                        continue;
        !           513:                nfound++;
        !           514:                if (p->p_stat == SZOMB) {
        !           515:                        retval[0] = p->p_pid;
        !           516: #if COMPAT_43
        !           517:                        if (compat)
        !           518:                                retval[1] = p->p_xstat;
        !           519:                        else
        !           520: #endif
        !           521:                        if (uap->status) {
        !           522:                                status = p->p_xstat;    /* convert to int */
        !           523:                                if (error = copyout((caddr_t)&status,
        !           524:                                    (caddr_t)uap->status,
        !           525:                                    sizeof(status)))
        !           526:                                        return (error);
        !           527:                        }
        !           528:                        if (uap->rusage &&
        !           529:                            (error = copyout((caddr_t)p->p_ru,
        !           530:                            (caddr_t)uap->rusage,
        !           531:                            sizeof (struct rusage))))
        !           532:                                return (error);
        !           533:                        /*
        !           534:                         * If we got the child via a ptrace 'attach',
        !           535:                         * we need to give it back to the old parent.
        !           536:                         */
        !           537:                        if (p->p_oppid && (t = pfind(p->p_oppid))) {
        !           538:                                p->p_oppid = 0;
        !           539:                                proc_reparent(p, t);
        !           540:                                psignal(t, SIGCHLD);
        !           541:                                wakeup((caddr_t)t);
        !           542:                                return (0);
        !           543:                        }
        !           544:                        p->p_xstat = 0;
        !           545:                        if (p->p_ru) {
        !           546:                                ruadd(&q->p_stats->p_cru, p->p_ru);
        !           547:                                FREE_ZONE(p->p_ru, sizeof *p->p_ru, M_ZOMBIE);
        !           548:                                p->p_ru = NULL;
        !           549:                        } else {
        !           550:                                printf("Warning : lost p_ru for %s\n", p->p_comm);
        !           551:                        }
        !           552: 
        !           553:                        /*
        !           554:                         * Decrement the count of procs running with this uid.
        !           555:                         */
        !           556:                        (void)chgproccnt(p->p_cred->p_ruid, -1);
        !           557: 
        !           558:                        /*
        !           559:                         * Free up credentials.
        !           560:                         */
        !           561:                        if (--p->p_cred->p_refcnt == 0) {
        !           562:                                struct ucred *ucr = p->p_ucred;
        !           563:                                struct pcred *pcr;
        !           564: 
        !           565:                                if (ucr != NOCRED) {
        !           566:                                        p->p_ucred = NOCRED;
        !           567:                                        crfree(ucr);
        !           568:                                }
        !           569:                                pcr = p->p_cred;
        !           570:                                p->p_cred = NULL;
        !           571:                                FREE_ZONE(pcr, sizeof *pcr, M_SUBPROC);
        !           572:                        }
        !           573: 
        !           574:                        /*
        !           575:                         * Release reference to text vnode
        !           576:                         */
        !           577:                        if (p->p_textvp)
        !           578:                                vrele(p->p_textvp);
        !           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:                        FREE_ZONE(p, sizeof *p, M_PROC);
        !           588:                        nprocs--;
        !           589:                        return (0);
        !           590:                }
        !           591:                if (p->p_stat == SSTOP && (p->p_flag & P_WAITED) == 0 &&
        !           592:                    (p->p_flag & P_TRACED || uap->options & WUNTRACED)) {
        !           593:                        p->p_flag |= P_WAITED;
        !           594:                        retval[0] = p->p_pid;
        !           595: #if COMPAT_43
        !           596:                        if (compat) {
        !           597:                                retval[1] = W_STOPCODE(p->p_xstat);
        !           598:                                error = 0;
        !           599:                        } else
        !           600: #endif
        !           601:                        if (uap->status) {
        !           602:                                status = W_STOPCODE(p->p_xstat);
        !           603:                                error = copyout((caddr_t)&status,
        !           604:                                    (caddr_t)uap->status,
        !           605:                                    sizeof(status));
        !           606:                        } else
        !           607:                                error = 0;
        !           608:                        return (error);
        !           609:                }
        !           610:        }
        !           611:        if (nfound == 0)
        !           612:                return (ECHILD);
        !           613:        if (uap->options & WNOHANG) {
        !           614:                retval[0] = 0;
        !           615:                return (0);
        !           616:        }
        !           617: 
        !           618:        if (error = tsleep0((caddr_t)q, PWAIT | PCATCH, "wait", 0, wait1continue)) {
        !           619:                return (error);
        !           620:        }
        !           621:        goto loop;
        !           622: }
        !           623: 
        !           624: /*
        !           625:  * make process 'parent' the new parent of process 'child'.
        !           626:  */
        !           627: void
        !           628: proc_reparent(child, parent)
        !           629:        register struct proc *child;
        !           630:        register struct proc *parent;
        !           631: {
        !           632: 
        !           633:        if (child->p_pptr == parent)
        !           634:                return;
        !           635: 
        !           636:        LIST_REMOVE(child, p_sibling);
        !           637:        LIST_INSERT_HEAD(&parent->p_children, child, p_sibling);
        !           638:        child->p_pptr = parent;
        !           639: }
        !           640: 
        !           641: kern_return_t
        !           642: init_process(void)
        !           643: /*
        !           644:  *     Make the current process an "init" process, meaning
        !           645:  *     that it doesn't have a parent, and that it won't be
        !           646:  *     gunned down by kill(-1, 0).
        !           647:  */
        !           648: {
        !           649:        register struct proc *p = current_proc();
        !           650: 
        !           651:        if (suser(p->p_ucred, &p->p_acflag))
        !           652:                return(KERN_NO_ACCESS);
        !           653: 
        !           654:        if (p->p_pid != 1 && p->p_pgid != p->p_pid)
        !           655:                enterpgrp(p, p->p_pid, 0);
        !           656:        p->p_flag |= P_SYSTEM;
        !           657: 
        !           658:        /*
        !           659:         *      Take us out of the sibling chain, and
        !           660:         *      out of our parent's child chain.
        !           661:         */
        !           662:        LIST_REMOVE(p, p_sibling);
        !           663:        p->p_sibling.le_prev = NULL;
        !           664:        p->p_sibling.le_next = NULL;
        !           665:        p->p_pptr = kernproc;
        !           666: 
        !           667:        return(KERN_SUCCESS);
        !           668: }
        !           669: 
        !           670: void
        !           671: process_terminate_self(void)
        !           672: {
        !           673:        struct proc *p = current_proc();
        !           674: 
        !           675:        if (p != NULL) {
        !           676:                exit1(p, W_EXITCODE(0, SIGKILL));
        !           677:                /*NOTREACHED*/
        !           678:        }
        !           679: }

unix.superglobalmegacorp.com

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