[source navigation] [diff markup] [identifier search] [freetext search] [file search]

Oldlinux Cross Reference
Linux/kernel/exit.c

Version: [1.0] [0.99.11] [0.99] [0.98] [0.97] [0.96a] [0.95] [0.12] [0.11] [0.01]
Architecture: [i386]

  1 /*
  2  *  linux/kernel/exit.c
  3  *
  4  *  (C) 1991  Linus Torvalds
  5  */
  6 
  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 
 35 static inline int send_sig(long sig,struct task_struct * p,int priv)
 36 {
 37         if (!p || sig<1 || sig>32)
 38                 return -EINVAL;
 39         if (priv || (current->euid==p->euid) || suser())
 40                 p->signal |= (1<<(sig-1));
 41         else
 42                 return -EPERM;
 43         return 0;
 44 }
 45 
 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)
 61 {
 62         struct task_struct **p = NR_TASKS + task;
 63         int err, retval = 0;
 64 
 65         if (!pid) while (--p > &FIRST_TASK) {
 66                 if (*p && (*p)->pgrp == current->pid) 
 67                         if (err=send_sig(sig,*p,1))
 68                                 retval = err;
 69         } else if (pid>0) while (--p > &FIRST_TASK) {
 70                 if (*p && (*p)->pid == pid) 
 71                         if (err=send_sig(sig,*p,0))
 72                                 retval = err;
 73         } else if (pid == -1) while (--p > &FIRST_TASK)
 74                 if (err = send_sig(sig,*p,0))
 75                         retval = err;
 76         else while (--p > &FIRST_TASK)
 77                 if (*p && (*p)->pgrp == -pid)
 78                         if (err = send_sig(sig,*p,0))
 79                                 retval = err;
 80         return retval;
 81 }
 82 
 83 static void tell_father(int pid)
 84 {
 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 */
 97 /* This is not really OK. Must change it to make father 1 */
 98         printk("BAD BAD - no father found\n\r");
 99         release(current);
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++)
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                 }
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;
122         iput(current->executable);
123         current->executable=NULL;
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;
128         if (current->leader)
129                 kill_session();
130         current->state = TASK_ZOMBIE;
131         current->exit_code = code;
132         tell_father(current->father);
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 
142 int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
143 {
144         int flag, code;
145         struct task_struct ** p;
146 
147         verify_area(stat_addr,4);
148 repeat:
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;
175                                 code = (*p)->exit_code;
176                                 release(*p);
177                                 put_fs_long(code,stat_addr);
178                                 return flag;
179                         default:
180                                 flag=1;
181                                 continue;
182                 }
183         }
184         if (flag) {
185                 if (options & WNOHANG)
186                         return 0;
187                 current->state=TASK_INTERRUPTIBLE;
188                 schedule();
189                 if (!(current->signal &= ~(1<<(SIGCHLD-1))))
190                         goto repeat;
191                 else
192                         return -EINTR;
193         }
194         return -ECHILD;
195 }
196 
197 
198 

[source navigation] [diff markup] [identifier search] [freetext search] [file search]

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.