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

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

unix.superglobalmegacorp.com

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