Annotation of linux/kernel/exit.c, revision 1.1.1.5

1.1.1.2   root        1: /*
                      2:  *  linux/kernel/exit.c
                      3:  *
                      4:  *  (C) 1991  Linus Torvalds
                      5:  */
                      6: 
1.1.1.4   root        7: #define DEBUG_PROC_TREE
                      8: 
1.1       root        9: #include <errno.h>
                     10: #include <signal.h>
                     11: #include <sys/wait.h>
                     12: 
                     13: #include <linux/sched.h>
                     14: #include <linux/kernel.h>
                     15: #include <linux/tty.h>
                     16: #include <asm/segment.h>
                     17: 
                     18: int sys_close(int fd);
                     19: 
1.1.1.5 ! root       20: inline int send_sig(long sig,struct task_struct * p,int priv)
        !            21: {
        !            22:        if (!p || (sig < 0) || (sig > 32))
        !            23:                return -EINVAL;
        !            24:        if (!priv && (current->euid!=p->euid) && !suser())
        !            25:                return -EPERM;
        !            26:        if (!sig)
        !            27:                return 0;
        !            28:        if ((sig == SIGKILL) || (sig == SIGCONT)) {
        !            29:                if (p->state == TASK_STOPPED)
        !            30:                        p->state = TASK_RUNNING;
        !            31:                p->exit_code = 0;
        !            32:                p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) |
        !            33:                                (1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) );
        !            34:        } 
        !            35:        /* Depends on order SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU */
        !            36:        if ((sig >= SIGSTOP) && (sig <= SIGTTOU)) 
        !            37:                p->signal &= ~(1<<(SIGCONT-1));
        !            38:        /* Actually deliver the signal */
        !            39:        p->signal |= (1<<(sig-1));
        !            40:        if (p->flags & PF_PTRACED) {
        !            41:                /* save the signal number for wait. */
        !            42:                p->exit_code = sig;
        !            43: 
        !            44:                /* we have to make sure the parent is awake. */
        !            45:                if (p->p_pptr != NULL && p->p_pptr->state == TASK_INTERRUPTIBLE)
        !            46:                        p->p_pptr->state = TASK_RUNNING;
        !            47: 
        !            48:                /* we have to make sure that the process stops. */
        !            49:                if (p->state == TASK_INTERRUPTIBLE || p->state == TASK_RUNNING)
        !            50:                        p->state = TASK_STOPPED;
        !            51: 
        !            52:                if (p == current)
        !            53:                        schedule();
        !            54:        }
        !            55:        return 0;
        !            56: }
        !            57: 
1.1       root       58: void release(struct task_struct * p)
                     59: {
                     60:        int i;
                     61: 
                     62:        if (!p)
                     63:                return;
1.1.1.4   root       64:        if (p == current) {
                     65:                printk("task releasing itself\n\r");
                     66:                return;
                     67:        }
1.1       root       68:        for (i=1 ; i<NR_TASKS ; i++)
                     69:                if (task[i]==p) {
                     70:                        task[i]=NULL;
1.1.1.4   root       71:                        /* Update links */
                     72:                        if (p->p_osptr)
                     73:                                p->p_osptr->p_ysptr = p->p_ysptr;
                     74:                        if (p->p_ysptr)
                     75:                                p->p_ysptr->p_osptr = p->p_osptr;
                     76:                        else
                     77:                                p->p_pptr->p_cptr = p->p_osptr;
1.1       root       78:                        free_page((long)p);
                     79:                        schedule();
                     80:                        return;
                     81:                }
                     82:        panic("trying to release non-existent task");
                     83: }
                     84: 
1.1.1.4   root       85: #ifdef DEBUG_PROC_TREE
                     86: /*
                     87:  * Check to see if a task_struct pointer is present in the task[] array
                     88:  * Return 0 if found, and 1 if not found.
                     89:  */
                     90: int bad_task_ptr(struct task_struct *p)
                     91: {
                     92:        int     i;
                     93: 
                     94:        if (!p)
                     95:                return 0;
                     96:        for (i=0 ; i<NR_TASKS ; i++)
                     97:                if (task[i] == p)
                     98:                        return 0;
                     99:        return 1;
                    100: }
                    101:        
                    102: /*
                    103:  * This routine scans the pid tree and make sure the rep invarient still
                    104:  * holds.  Used for debugging only, since it's very slow....
                    105:  *
                    106:  * It looks a lot scarier than it really is.... we're doing ænothing more
                    107:  * than verifying the doubly-linked list foundæin p_ysptr and p_osptr, 
                    108:  * and checking it corresponds with the process tree defined by p_cptr and 
                    109:  * p_pptr;
                    110:  */
                    111: void audit_ptree()
                    112: {
                    113:        int     i;
                    114: 
                    115:        for (i=1 ; i<NR_TASKS ; i++) {
                    116:                if (!task[i])
                    117:                        continue;
                    118:                if (bad_task_ptr(task[i]->p_pptr))
                    119:                        printk("Warning, pid %d's parent link is bad\n",
                    120:                                task[i]->pid);
                    121:                if (bad_task_ptr(task[i]->p_cptr))
                    122:                        printk("Warning, pid %d's child link is bad\n",
                    123:                                task[i]->pid);
                    124:                if (bad_task_ptr(task[i]->p_ysptr))
                    125:                        printk("Warning, pid %d's ys link is bad\n",
                    126:                                task[i]->pid);
                    127:                if (bad_task_ptr(task[i]->p_osptr))
                    128:                        printk("Warning, pid %d's os link is bad\n",
                    129:                                task[i]->pid);
                    130:                if (task[i]->p_pptr == task[i])
                    131:                        printk("Warning, pid %d parent link points to self\n");
                    132:                if (task[i]->p_cptr == task[i])
                    133:                        printk("Warning, pid %d child link points to self\n");
                    134:                if (task[i]->p_ysptr == task[i])
                    135:                        printk("Warning, pid %d ys link points to self\n");
                    136:                if (task[i]->p_osptr == task[i])
                    137:                        printk("Warning, pid %d os link points to self\n");
                    138:                if (task[i]->p_osptr) {
                    139:                        if (task[i]->p_pptr != task[i]->p_osptr->p_pptr)
                    140:                                printk(
                    141:                        "Warning, pid %d older sibling %d parent is %d\n",
                    142:                                task[i]->pid, task[i]->p_osptr->pid,
                    143:                                task[i]->p_osptr->p_pptr->pid);
                    144:                        if (task[i]->p_osptr->p_ysptr != task[i])
                    145:                                printk(
                    146:                "Warning, pid %d older sibling %d has mismatched ys link\n",
                    147:                                task[i]->pid, task[i]->p_osptr->pid);
                    148:                }
                    149:                if (task[i]->p_ysptr) {
                    150:                        if (task[i]->p_pptr != task[i]->p_ysptr->p_pptr)
                    151:                                printk(
                    152:                        "Warning, pid %d younger sibling %d parent is %d\n",
                    153:                                task[i]->pid, task[i]->p_osptr->pid,
                    154:                                task[i]->p_osptr->p_pptr->pid);
                    155:                        if (task[i]->p_ysptr->p_osptr != task[i])
                    156:                                printk(
                    157:                "Warning, pid %d younger sibling %d has mismatched os link\n",
                    158:                                task[i]->pid, task[i]->p_ysptr->pid);
                    159:                }
                    160:                if (task[i]->p_cptr) {
                    161:                        if (task[i]->p_cptr->p_pptr != task[i])
                    162:                                printk(
                    163:                        "Warning, pid %d youngest child %d has mismatched parent link\n",
                    164:                                task[i]->pid, task[i]->p_cptr->pid);
                    165:                        if (task[i]->p_cptr->p_ysptr)
                    166:                                printk(
                    167:                        "Warning, pid %d youngest child %d has non-NULL ys link\n",
                    168:                                task[i]->pid, task[i]->p_cptr->pid);
                    169:                }
                    170:        }
                    171: }
                    172: #endif /* DEBUG_PROC_TREE */
                    173: 
                    174: int session_of_pgrp(int pgrp)
1.1.1.2   root      175: {
1.1.1.4   root      176:        struct task_struct **p;
                    177: 
                    178:        for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
                    179:                if ((*p)->pgrp == pgrp)
                    180:                        return((*p)->session);
                    181:        return -1;
                    182: }
                    183: 
                    184: int kill_pg(int pgrp, int sig, int priv)
                    185: {
                    186:        struct task_struct **p;
                    187:        int err,retval = -ESRCH;
                    188:        int found = 0;
                    189: 
1.1.1.5 ! root      190:        if (sig<0 || sig>32 || pgrp<=0)
1.1.1.4   root      191:                return -EINVAL;
                    192:        for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
                    193:                if ((*p)->pgrp == pgrp) {
                    194:                        if (sig && (err = send_sig(sig,*p,priv)))
                    195:                                retval = err;
                    196:                        else
                    197:                                found++;
                    198:                }
                    199:        return(found ? 0 : retval);
                    200: }
                    201: 
                    202: int kill_proc(int pid, int sig, int priv)
                    203: {
                    204:        struct task_struct **p;
                    205: 
1.1.1.5 ! root      206:        if (sig<0 || sig>32)
1.1.1.4   root      207:                return -EINVAL;
                    208:        for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
                    209:                if ((*p)->pid == pid)
                    210:                        return(sig ? send_sig(sig,*p,priv) : 0);
                    211:        return(-ESRCH);
1.1.1.2   root      212: }
                    213: 
                    214: /*
1.1.1.4   root      215:  * POSIX specifies that kill(-1,sig) is unspecified, but what we have
                    216:  * is probably wrong.  Should make it like BSD or SYSV.
1.1.1.2   root      217:  */
                    218: int sys_kill(int pid,int sig)
1.1       root      219: {
                    220:        struct task_struct **p = NR_TASKS + task;
1.1.1.2   root      221:        int err, retval = 0;
1.1       root      222: 
1.1.1.4   root      223:        if (!pid)
                    224:                return(kill_pg(current->pid,sig,0));
                    225:        if (pid == -1) {
                    226:                while (--p > &FIRST_TASK)
1.1.1.2   root      227:                        if (err = send_sig(sig,*p,0))
                    228:                                retval = err;
1.1.1.4   root      229:                return(retval);
                    230:        }
                    231:        if (pid < 0) 
                    232:                return(kill_pg(-pid,sig,0));
                    233:        /* Normal kill */
                    234:        return(kill_proc(pid,sig,0));
1.1       root      235: }
                    236: 
1.1.1.4   root      237: /*
                    238:  * Determine if a process group is "orphaned", according to the POSIX
                    239:  * definition in 2.2.2.52.  Orphaned process groups are not to be affected
                    240:  * by terminal-generated stop signals.  Newly orphaned process groups are 
                    241:  * to receive a SIGHUP and a SIGCONT.
                    242:  * 
                    243:  * "I ask you, have you ever known what it is to be an orphan?"
                    244:  */
                    245: int is_orphaned_pgrp(int pgrp)
1.1       root      246: {
1.1.1.4   root      247:        struct task_struct **p;
1.1.1.2   root      248: 
1.1.1.4   root      249:        for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
                    250:                if (!(*p) ||
                    251:                    ((*p)->pgrp != pgrp) || 
                    252:                    ((*p)->state == TASK_ZOMBIE) ||
                    253:                    ((*p)->p_pptr->pid == 1))
                    254:                        continue;
                    255:                if (((*p)->p_pptr->pgrp != pgrp) &&
                    256:                    ((*p)->p_pptr->session == (*p)->session))
                    257:                        return 0;
                    258:        }
                    259:        return(1);      /* (sighing) "Often!" */
1.1       root      260: }
                    261: 
1.1.1.4   root      262: static int has_stopped_jobs(int pgrp)
1.1       root      263: {
1.1.1.4   root      264:        struct task_struct ** p;
                    265: 
                    266:        for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
                    267:                if ((*p)->pgrp != pgrp)
                    268:                        continue;
                    269:                if ((*p)->state == TASK_STOPPED)
                    270:                        return(1);
                    271:        }
                    272:        return(0);
                    273: }
                    274: 
                    275: volatile void do_exit(long code)
                    276: {
                    277:        struct task_struct *p;
1.1       root      278:        int i;
                    279: 
                    280:        free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
                    281:        free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
                    282:        for (i=0 ; i<NR_OPEN ; i++)
                    283:                if (current->filp[i])
                    284:                        sys_close(i);
                    285:        iput(current->pwd);
1.1.1.4   root      286:        current->pwd = NULL;
1.1       root      287:        iput(current->root);
1.1.1.4   root      288:        current->root = NULL;
1.1.1.3   root      289:        iput(current->executable);
1.1.1.4   root      290:        current->executable = NULL;
                    291:        iput(current->library);
                    292:        current->library = NULL;
1.1.1.2   root      293:        current->state = TASK_ZOMBIE;
                    294:        current->exit_code = code;
1.1.1.4   root      295:        /* 
                    296:         * Check to see if any process groups have become orphaned
                    297:         * as a result of our exiting, and if they have any stopped
                    298:         * jobs, send them a SIGUP and then a SIGCONT.  (POSIX 3.2.2.2)
                    299:         *
                    300:         * Case i: Our father is in a different pgrp than we are
                    301:         * and we were the only connection outside, so our pgrp
                    302:         * is about to become orphaned.
                    303:         */
                    304:        if ((current->p_pptr->pgrp != current->pgrp) &&
                    305:            (current->p_pptr->session == current->session) &&
                    306:            is_orphaned_pgrp(current->pgrp) &&
                    307:            has_stopped_jobs(current->pgrp)) {
                    308:                kill_pg(current->pgrp,SIGHUP,1);
                    309:                kill_pg(current->pgrp,SIGCONT,1);
                    310:        }
                    311:        /* Let father know we died */
1.1.1.5 ! root      312:        send_sig (SIGCHLD, current->p_pptr, 1);
1.1.1.4   root      313:        
                    314:        /*
                    315:         * This loop does two things:
                    316:         * 
                    317:         * A.  Make init inherit all the child processes
                    318:         * B.  Check to see if any process groups have become orphaned
                    319:         *      as a result of our exiting, and if they have any stopped
                    320:         *      jons, send them a SIGUP and then a SIGCONT.  (POSIX 3.2.2.2)
                    321:         */
                    322:        if (p = current->p_cptr) {
                    323:                while (1) {
1.1.1.5 ! root      324:                        p->flags &= ~PF_PTRACED;
1.1.1.4   root      325:                        p->p_pptr = task[1];
                    326:                        if (p->state == TASK_ZOMBIE)
                    327:                                task[1]->signal |= (1<<(SIGCHLD-1));
                    328:                        /*
                    329:                         * process group orphan check
                    330:                         * Case ii: Our child is in a different pgrp 
                    331:                         * than we are, and it was the only connection
                    332:                         * outside, so the child pgrp is now orphaned.
                    333:                         */
                    334:                        if ((p->pgrp != current->pgrp) &&
                    335:                            (p->session == current->session) &&
                    336:                            is_orphaned_pgrp(p->pgrp) &&
                    337:                            has_stopped_jobs(p->pgrp)) {
                    338:                                kill_pg(p->pgrp,SIGHUP,1);
                    339:                                kill_pg(p->pgrp,SIGCONT,1);
                    340:                        }
                    341:                        if (p->p_osptr) {
                    342:                                p = p->p_osptr;
                    343:                                continue;
                    344:                        }
                    345:                        /*
                    346:                         * This is it; link everything into init's children 
                    347:                         * and leave 
                    348:                         */
                    349:                        p->p_osptr = task[1]->p_cptr;
                    350:                        task[1]->p_cptr->p_ysptr = p;
                    351:                        task[1]->p_cptr = current->p_cptr;
                    352:                        current->p_cptr = 0;
                    353:                        break;
                    354:                }
                    355:        }
                    356:        if (current->leader) {
                    357:                struct task_struct **p;
                    358:                struct tty_struct *tty;
                    359: 
                    360:                if (current->tty >= 0) {
                    361:                        tty = TTY_TABLE(current->tty);
                    362:                        if (tty->pgrp>0)
                    363:                                kill_pg(tty->pgrp, SIGHUP, 1);
                    364:                        tty->pgrp = 0;
                    365:                        tty->session = 0;
                    366:                }
                    367:                for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
                    368:                        if ((*p)->session == current->session)
                    369:                                (*p)->tty = -1;
                    370:        }
                    371:        if (last_task_used_math == current)
                    372:                last_task_used_math = NULL;
                    373: #ifdef DEBUG_PROC_TREE
                    374:        audit_ptree();
                    375: #endif
1.1       root      376:        schedule();
                    377: }
                    378: 
                    379: int sys_exit(int error_code)
                    380: {
1.1.1.4   root      381:        do_exit((error_code&0xff)<<8);
1.1       root      382: }
                    383: 
1.1.1.2   root      384: int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
1.1       root      385: {
1.1.1.4   root      386:        int flag;
                    387:        struct task_struct *p;
                    388:        unsigned long oldblocked;
1.1       root      389: 
1.1.1.5 ! root      390:        if (stat_addr)
        !           391:                verify_area(stat_addr,4);
1.1       root      392: repeat:
1.1.1.2   root      393:        flag=0;
1.1.1.4   root      394:        for (p = current->p_cptr ; p ; p = p->p_osptr) {
1.1.1.2   root      395:                if (pid>0) {
1.1.1.4   root      396:                        if (p->pid != pid)
1.1.1.2   root      397:                                continue;
                    398:                } else if (!pid) {
1.1.1.4   root      399:                        if (p->pgrp != current->pgrp)
1.1.1.2   root      400:                                continue;
                    401:                } else if (pid != -1) {
1.1.1.4   root      402:                        if (p->pgrp != -pid)
1.1.1.2   root      403:                                continue;
                    404:                }
1.1.1.4   root      405:                switch (p->state) {
1.1.1.2   root      406:                        case TASK_STOPPED:
1.1.1.4   root      407:                                if (!(options & WUNTRACED) || 
                    408:                                    !p->exit_code)
1.1.1.2   root      409:                                        continue;
1.1.1.5 ! root      410:                                if (stat_addr)
        !           411:                                        put_fs_long((p->exit_code << 8) | 0x7f,
        !           412:                                                stat_addr);
1.1.1.4   root      413:                                p->exit_code = 0;
                    414:                                return p->pid;
1.1.1.2   root      415:                        case TASK_ZOMBIE:
1.1.1.4   root      416:                                current->cutime += p->utime;
                    417:                                current->cstime += p->stime;
                    418:                                flag = p->pid;
1.1.1.5 ! root      419:                                if (stat_addr)
        !           420:                                        put_fs_long(p->exit_code, stat_addr);
1.1.1.4   root      421:                                release(p);
                    422: #ifdef DEBUG_PROC_TREE
                    423:                                audit_ptree();
                    424: #endif
1.1.1.2   root      425:                                return flag;
                    426:                        default:
1.1       root      427:                                flag=1;
1.1.1.2   root      428:                                continue;
                    429:                }
                    430:        }
1.1       root      431:        if (flag) {
                    432:                if (options & WNOHANG)
                    433:                        return 0;
1.1.1.2   root      434:                current->state=TASK_INTERRUPTIBLE;
1.1.1.4   root      435:                oldblocked = current->blocked;
                    436:                current->blocked &= ~(1<<(SIGCHLD-1));
1.1.1.2   root      437:                schedule();
1.1.1.4   root      438:                current->blocked = oldblocked;
                    439:                if (current->signal & ~(current->blocked | (1<<(SIGCHLD-1))))
                    440:                        return -ERESTARTSYS;
1.1       root      441:                else
1.1.1.4   root      442:                        goto repeat;
1.1       root      443:        }
                    444:        return -ECHILD;
                    445: }
                    446: 
                    447: 

unix.superglobalmegacorp.com