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