Annotation of XNU/bsd/kern/kern_exit.c, revision 1.1.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.