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

1.1.1.2   root        1: /*
                      2:  *  linux/kernel/exit.c
                      3:  *
                      4:  *  (C) 1991  Linus Torvalds
                      5:  */
                      6: 
1.1       root        7: #include <errno.h>
                      8: #include <signal.h>
                      9: #include <sys/wait.h>
                     10: 
                     11: #include <linux/sched.h>
                     12: #include <linux/kernel.h>
                     13: #include <linux/tty.h>
                     14: #include <asm/segment.h>
                     15: 
                     16: int sys_pause(void);
                     17: int sys_close(int fd);
                     18: 
                     19: void release(struct task_struct * p)
                     20: {
                     21:        int i;
                     22: 
                     23:        if (!p)
                     24:                return;
                     25:        for (i=1 ; i<NR_TASKS ; i++)
                     26:                if (task[i]==p) {
                     27:                        task[i]=NULL;
                     28:                        free_page((long)p);
                     29:                        schedule();
                     30:                        return;
                     31:                }
                     32:        panic("trying to release non-existent task");
                     33: }
                     34: 
1.1.1.2   root       35: static inline int send_sig(long sig,struct task_struct * p,int priv)
1.1       root       36: {
                     37:        if (!p || sig<1 || sig>32)
1.1.1.2   root       38:                return -EINVAL;
                     39:        if (priv || (current->euid==p->euid) || suser())
1.1       root       40:                p->signal |= (1<<(sig-1));
1.1.1.2   root       41:        else
                     42:                return -EPERM;
                     43:        return 0;
1.1       root       44: }
                     45: 
1.1.1.2   root       46: static void kill_session(void)
                     47: {
                     48:        struct task_struct **p = NR_TASKS + task;
                     49:        
                     50:        while (--p > &FIRST_TASK) {
                     51:                if (*p && (*p)->session == current->session)
                     52:                        (*p)->signal |= 1<<(SIGHUP-1);
                     53:        }
                     54: }
                     55: 
                     56: /*
                     57:  * XXX need to check permissions needed to send signals to process
                     58:  * groups, etc. etc.  kill() permissions semantics are tricky!
                     59:  */
                     60: int sys_kill(int pid,int sig)
1.1       root       61: {
                     62:        struct task_struct **p = NR_TASKS + task;
1.1.1.2   root       63:        int err, retval = 0;
1.1       root       64: 
                     65:        if (!pid) while (--p > &FIRST_TASK) {
1.1.1.2   root       66:                if (*p && (*p)->pgrp == current->pid) 
                     67:                        if (err=send_sig(sig,*p,1))
                     68:                                retval = err;
1.1       root       69:        } else if (pid>0) while (--p > &FIRST_TASK) {
1.1.1.2   root       70:                if (*p && (*p)->pid == pid) 
                     71:                        if (err=send_sig(sig,*p,0))
                     72:                                retval = err;
1.1       root       73:        } else if (pid == -1) while (--p > &FIRST_TASK)
1.1.1.2   root       74:                if (err = send_sig(sig,*p,0))
                     75:                        retval = err;
1.1       root       76:        else while (--p > &FIRST_TASK)
                     77:                if (*p && (*p)->pgrp == -pid)
1.1.1.2   root       78:                        if (err = send_sig(sig,*p,0))
                     79:                                retval = err;
                     80:        return retval;
1.1       root       81: }
                     82: 
1.1.1.2   root       83: static void tell_father(int pid)
1.1       root       84: {
1.1.1.2   root       85:        int i;
                     86: 
                     87:        if (pid)
                     88:                for (i=0;i<NR_TASKS;i++) {
                     89:                        if (!task[i])
                     90:                                continue;
                     91:                        if (task[i]->pid != pid)
                     92:                                continue;
                     93:                        task[i]->signal |= (1<<(SIGCHLD-1));
                     94:                        return;
                     95:                }
                     96: /* if we don't find any fathers, we just release ourselves */
1.1.1.3 ! root       97: /* This is not really OK. Must change it to make father 1 */
        !            98:        printk("BAD BAD - no father found\n\r");
1.1.1.2   root       99:        release(current);
1.1       root      100: }
                    101: 
                    102: int do_exit(long code)
                    103: {
                    104:        int i;
                    105: 
                    106:        free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
                    107:        free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
                    108:        for (i=0 ; i<NR_TASKS ; i++)
1.1.1.3 ! root      109:                if (task[i] && task[i]->father == current->pid) {
        !           110:                        task[i]->father = 1;
        !           111:                        if (task[i]->state == TASK_ZOMBIE)
        !           112:                                /* assumption task[1] is always init */
        !           113:                                (void) send_sig(SIGCHLD, task[1], 1);
        !           114:                }
1.1       root      115:        for (i=0 ; i<NR_OPEN ; i++)
                    116:                if (current->filp[i])
                    117:                        sys_close(i);
                    118:        iput(current->pwd);
                    119:        current->pwd=NULL;
                    120:        iput(current->root);
                    121:        current->root=NULL;
1.1.1.3 ! root      122:        iput(current->executable);
        !           123:        current->executable=NULL;
1.1       root      124:        if (current->leader && current->tty >= 0)
                    125:                tty_table[current->tty].pgrp = 0;
                    126:        if (last_task_used_math == current)
                    127:                last_task_used_math = NULL;
1.1.1.2   root      128:        if (current->leader)
                    129:                kill_session();
                    130:        current->state = TASK_ZOMBIE;
                    131:        current->exit_code = code;
                    132:        tell_father(current->father);
1.1       root      133:        schedule();
                    134:        return (-1);    /* just to suppress warnings */
                    135: }
                    136: 
                    137: int sys_exit(int error_code)
                    138: {
                    139:        return do_exit((error_code&0xff)<<8);
                    140: }
                    141: 
1.1.1.2   root      142: int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
1.1       root      143: {
1.1.1.3 ! root      144:        int flag, code;
1.1       root      145:        struct task_struct ** p;
                    146: 
                    147:        verify_area(stat_addr,4);
                    148: repeat:
1.1.1.2   root      149:        flag=0;
                    150:        for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
                    151:                if (!*p || *p == current)
                    152:                        continue;
                    153:                if ((*p)->father != current->pid)
                    154:                        continue;
                    155:                if (pid>0) {
                    156:                        if ((*p)->pid != pid)
                    157:                                continue;
                    158:                } else if (!pid) {
                    159:                        if ((*p)->pgrp != current->pgrp)
                    160:                                continue;
                    161:                } else if (pid != -1) {
                    162:                        if ((*p)->pgrp != -pid)
                    163:                                continue;
                    164:                }
                    165:                switch ((*p)->state) {
                    166:                        case TASK_STOPPED:
                    167:                                if (!(options & WUNTRACED))
                    168:                                        continue;
                    169:                                put_fs_long(0x7f,stat_addr);
                    170:                                return (*p)->pid;
                    171:                        case TASK_ZOMBIE:
                    172:                                current->cutime += (*p)->utime;
                    173:                                current->cstime += (*p)->stime;
                    174:                                flag = (*p)->pid;
1.1.1.3 ! root      175:                                code = (*p)->exit_code;
1.1.1.2   root      176:                                release(*p);
1.1.1.3 ! root      177:                                put_fs_long(code,stat_addr);
1.1.1.2   root      178:                                return flag;
                    179:                        default:
1.1       root      180:                                flag=1;
1.1.1.2   root      181:                                continue;
                    182:                }
                    183:        }
1.1       root      184:        if (flag) {
                    185:                if (options & WNOHANG)
                    186:                        return 0;
1.1.1.2   root      187:                current->state=TASK_INTERRUPTIBLE;
                    188:                schedule();
1.1       root      189:                if (!(current->signal &= ~(1<<(SIGCHLD-1))))
                    190:                        goto repeat;
                    191:                else
                    192:                        return -EINTR;
                    193:        }
                    194:        return -ECHILD;
                    195: }
                    196: 
                    197: 

unix.superglobalmegacorp.com