root/kernel/exit.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. send_sig
  2. release
  3. bad_task_ptr
  4. audit_ptree
  5. session_of_pgrp
  6. kill_pg
  7. kill_wait
  8. kill_proc
  9. sys_kill
  10. is_orphaned_pgrp
  11. has_stopped_jobs
  12. forget_original_parent
  13. do_exit
  14. sys_exit
  15. sys_wait4
  16. sys_waitpid

   1 /*
   2  *  linux/kernel/exit.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 #define DEBUG_PROC_TREE
   8 
   9 #include <linux/wait.h>
  10 #include <linux/errno.h>
  11 #include <linux/signal.h>
  12 #include <linux/sched.h>
  13 #include <linux/kernel.h>
  14 #include <linux/resource.h>
  15 #include <linux/mm.h>
  16 #include <linux/tty.h>
  17 
  18 #include <asm/segment.h>
  19 
  20 int sys_close(int fd);
  21 void getrusage(struct task_struct *, int, struct rusage *);
  22 
  23 int send_sig(long sig,struct task_struct * p,int priv)
     /* [previous][next][first][last][top][bottom][index][help] */
  24 {
  25         if (!p || (sig < 0) || (sig > 32))
  26                 return -EINVAL;
  27         if (!priv && ((sig != SIGCONT) || (current->session != p->session)) &&
  28             (current->euid != p->euid) && (current->uid != p->uid) && !suser())
  29                 return -EPERM;
  30         if (!sig)
  31                 return 0;
  32         if ((sig == SIGKILL) || (sig == SIGCONT)) {
  33                 if (p->state == TASK_STOPPED)
  34                         p->state = TASK_RUNNING;
  35                 p->exit_code = 0;
  36                 p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) |
  37                                 (1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) );
  38         } 
  39         /* Depends on order SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU */
  40         if ((sig >= SIGSTOP) && (sig <= SIGTTOU)) 
  41                 p->signal &= ~(1<<(SIGCONT-1));
  42         /* Actually deliver the signal */
  43         p->signal |= (1<<(sig-1));
  44         if (p->flags & PF_PTRACED) {
  45                 /* save the signal number for wait. */
  46                 p->exit_code = sig;
  47 
  48                 /* we have to make sure the parent process is awake. */
  49                 if (p->p_pptr != NULL && p->p_pptr->state == TASK_INTERRUPTIBLE)
  50                         p->p_pptr->state = TASK_RUNNING;
  51 
  52                 /* we have to make sure that the process stops. */
  53                 if (p->state == TASK_INTERRUPTIBLE || p->state == TASK_RUNNING)
  54                         p->state = TASK_STOPPED;
  55         }
  56         return 0;
  57 }
  58 
  59 void release(struct task_struct * p)
     /* [previous][next][first][last][top][bottom][index][help] */
  60 {
  61         int i;
  62 
  63         if (!p)
  64                 return;
  65         if (p == current) {
  66                 printk("task releasing itself\n\r");
  67                 return;
  68         }
  69         for (i=1 ; i<NR_TASKS ; i++)
  70                 if (task[i] == p) {
  71                         task[i] = NULL;
  72                         REMOVE_LINKS(p);
  73                         free_page((long) p);
  74                         return;
  75                 }
  76         panic("trying to release non-existent task");
  77 }
  78 
  79 #ifdef DEBUG_PROC_TREE
  80 /*
  81  * Check to see if a task_struct pointer is present in the task[] array
  82  * Return 0 if found, and 1 if not found.
  83  */
  84 int bad_task_ptr(struct task_struct *p)
     /* [previous][next][first][last][top][bottom][index][help] */
  85 {
  86         int     i;
  87 
  88         if (!p)
  89                 return 0;
  90         for (i=0 ; i<NR_TASKS ; i++)
  91                 if (task[i] == p)
  92                         return 0;
  93         return 1;
  94 }
  95         
  96 /*
  97  * This routine scans the pid tree and make sure the rep invarient still
  98  * holds.  Used for debugging only, since it's very slow....
  99  *
 100  * It looks a lot scarier than it really is.... we're doing ænothing more
 101  * than verifying the doubly-linked list foundæin p_ysptr and p_osptr, 
 102  * and checking it corresponds with the process tree defined by p_cptr and 
 103  * p_pptr;
 104  */
 105 void audit_ptree()
     /* [previous][next][first][last][top][bottom][index][help] */
 106 {
 107         int     i;
 108 
 109         for (i=1 ; i<NR_TASKS ; i++) {
 110                 if (!task[i])
 111                         continue;
 112                 if (bad_task_ptr(task[i]->p_pptr))
 113                         printk("Warning, pid %d's parent link is bad\n",
 114                                 task[i]->pid);
 115                 if (bad_task_ptr(task[i]->p_cptr))
 116                         printk("Warning, pid %d's child link is bad\n",
 117                                 task[i]->pid);
 118                 if (bad_task_ptr(task[i]->p_ysptr))
 119                         printk("Warning, pid %d's ys link is bad\n",
 120                                 task[i]->pid);
 121                 if (bad_task_ptr(task[i]->p_osptr))
 122                         printk("Warning, pid %d's os link is bad\n",
 123                                 task[i]->pid);
 124                 if (task[i]->p_pptr == task[i])
 125                         printk("Warning, pid %d parent link points to self\n");
 126                 if (task[i]->p_cptr == task[i])
 127                         printk("Warning, pid %d child link points to self\n");
 128                 if (task[i]->p_ysptr == task[i])
 129                         printk("Warning, pid %d ys link points to self\n");
 130                 if (task[i]->p_osptr == task[i])
 131                         printk("Warning, pid %d os link points to self\n");
 132                 if (task[i]->p_osptr) {
 133                         if (task[i]->p_pptr != task[i]->p_osptr->p_pptr)
 134                                 printk(
 135                         "Warning, pid %d older sibling %d parent is %d\n",
 136                                 task[i]->pid, task[i]->p_osptr->pid,
 137                                 task[i]->p_osptr->p_pptr->pid);
 138                         if (task[i]->p_osptr->p_ysptr != task[i])
 139                                 printk(
 140                 "Warning, pid %d older sibling %d has mismatched ys link\n",
 141                                 task[i]->pid, task[i]->p_osptr->pid);
 142                 }
 143                 if (task[i]->p_ysptr) {
 144                         if (task[i]->p_pptr != task[i]->p_ysptr->p_pptr)
 145                                 printk(
 146                         "Warning, pid %d younger sibling %d parent is %d\n",
 147                                 task[i]->pid, task[i]->p_osptr->pid,
 148                                 task[i]->p_osptr->p_pptr->pid);
 149                         if (task[i]->p_ysptr->p_osptr != task[i])
 150                                 printk(
 151                 "Warning, pid %d younger sibling %d has mismatched os link\n",
 152                                 task[i]->pid, task[i]->p_ysptr->pid);
 153                 }
 154                 if (task[i]->p_cptr) {
 155                         if (task[i]->p_cptr->p_pptr != task[i])
 156                                 printk(
 157                         "Warning, pid %d youngest child %d has mismatched parent link\n",
 158                                 task[i]->pid, task[i]->p_cptr->pid);
 159                         if (task[i]->p_cptr->p_ysptr)
 160                                 printk(
 161                         "Warning, pid %d youngest child %d has non-NULL ys link\n",
 162                                 task[i]->pid, task[i]->p_cptr->pid);
 163                 }
 164         }
 165 }
 166 #endif /* DEBUG_PROC_TREE */
 167 
 168 /*
 169  * This checks not only the pgrp, but falls back on the pid if no
 170  * satisfactory prgp is found. I dunno - gdb doesn't work correctly
 171  * without this...
 172  */
 173 int session_of_pgrp(int pgrp)
     /* [previous][next][first][last][top][bottom][index][help] */
 174 {
 175         struct task_struct **p;
 176         int fallback;
 177 
 178         fallback = -1;
 179         for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
 180                 if (!*p || (*p)->session <= 0)
 181                         continue;
 182                 if ((*p)->pgrp == pgrp)
 183                         return (*p)->session;
 184                 if ((*p)->pid == pgrp)
 185                         fallback = (*p)->session;
 186         }
 187         return fallback;
 188 }
 189 
 190 int kill_pg(int pgrp, int sig, int priv)
     /* [previous][next][first][last][top][bottom][index][help] */
 191 {
 192         struct task_struct **p;
 193         int err,retval = -ESRCH;
 194         int found = 0;
 195 
 196         if (sig<0 || sig>32 || pgrp<=0)
 197                 return -EINVAL;
 198         for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
 199                 if (*p && (*p)->pgrp == pgrp) {
 200                         if (sig && (err = send_sig(sig,*p,priv)))
 201                                 retval = err;
 202                         else
 203                                 found++;
 204                 }
 205         return(found ? 0 : retval);
 206 }
 207 
 208 /* This routine is used by vhangup.  It send's sigkill to everything
 209    waiting on a particular wait_queue.  It assumes root privledges.
 210    We don't want to destroy the wait queue here, because the caller
 211    should call wake_up immediately after calling kill_wait. */
 212 
 213 void
 214 kill_wait (struct wait_queue **q, int sig)
     /* [previous][next][first][last][top][bottom][index][help] */
 215 {
 216    struct wait_queue *next;
 217    struct wait_queue *tmp;
 218    struct task_struct *p;
 219    
 220    if (!q || !(next = *q))
 221      return;
 222    do { 
 223       tmp = next;
 224       next = tmp->next;
 225       if (p = tmp->task)
 226         {
 227            send_sig (sig, p , 1);
 228         }
 229    } while (next && next != *q);
 230 }
 231 
 232 int kill_proc(int pid, int sig, int priv)
     /* [previous][next][first][last][top][bottom][index][help] */
 233 {
 234         struct task_struct **p;
 235 
 236         if (sig<0 || sig>32)
 237                 return -EINVAL;
 238         for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
 239                 if (*p && (*p)->pid == pid)
 240                         return(sig ? send_sig(sig,*p,priv) : 0);
 241         return(-ESRCH);
 242 }
 243 
 244 /*
 245  * POSIX specifies that kill(-1,sig) is unspecified, but what we have
 246  * is probably wrong.  Should make it like BSD or SYSV.
 247  */
 248 int sys_kill(int pid,int sig)
     /* [previous][next][first][last][top][bottom][index][help] */
 249 {
 250         struct task_struct **p = NR_TASKS + task;
 251         int err, retval = 0, count = 0;
 252 
 253         if (!pid)
 254                 return(kill_pg(current->pgrp,sig,0));
 255         if (pid == -1) {
 256                 while (--p > &FIRST_TASK)
 257                         if (*p && (*p)->pid > 1 && *p != current) {
 258                                 ++count;
 259                                 if ((err = send_sig(sig,*p,0)) != -EPERM)
 260                                         retval = err;
 261                         }
 262                 return(count ? retval : -ESRCH);
 263         }
 264         if (pid < 0) 
 265                 return(kill_pg(-pid,sig,0));
 266         /* Normal kill */
 267         return(kill_proc(pid,sig,0));
 268 }
 269 
 270 /*
 271  * Determine if a process group is "orphaned", according to the POSIX
 272  * definition in 2.2.2.52.  Orphaned process groups are not to be affected
 273  * by terminal-generated stop signals.  Newly orphaned process groups are 
 274  * to receive a SIGHUP and a SIGCONT.
 275  * 
 276  * "I ask you, have you ever known what it is to be an orphan?"
 277  */
 278 int is_orphaned_pgrp(int pgrp)
     /* [previous][next][first][last][top][bottom][index][help] */
 279 {
 280         struct task_struct **p;
 281 
 282         for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
 283                 if (!(*p) ||
 284                     ((*p)->pgrp != pgrp) || 
 285                     ((*p)->state == TASK_ZOMBIE) ||
 286                     ((*p)->p_pptr->pid == 1))
 287                         continue;
 288                 if (((*p)->p_pptr->pgrp != pgrp) &&
 289                     ((*p)->p_pptr->session == (*p)->session))
 290                         return 0;
 291         }
 292         return(1);      /* (sighing) "Often!" */
 293 }
 294 
 295 static int has_stopped_jobs(int pgrp)
     /* [previous][next][first][last][top][bottom][index][help] */
 296 {
 297         struct task_struct ** p;
 298 
 299         for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
 300                 if (!*p || (*p)->pgrp != pgrp)
 301                         continue;
 302                 if ((*p)->state == TASK_STOPPED)
 303                         return(1);
 304         }
 305         return(0);
 306 }
 307 
 308 static void forget_original_parent(struct task_struct * father)
     /* [previous][next][first][last][top][bottom][index][help] */
 309 {
 310         struct task_struct ** p;
 311 
 312         for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
 313                 if (*p && (*p)->p_opptr == father)
 314                         if (task[1])
 315                                 (*p)->p_opptr = task[1];
 316                         else
 317                                 (*p)->p_opptr = task[0];
 318 }
 319 
 320 volatile void do_exit(long code)
     /* [previous][next][first][last][top][bottom][index][help] */
 321 {
 322         struct task_struct *p;
 323         int i;
 324 
 325 fake_volatile:
 326         free_page_tables(current);
 327         for (i=0 ; i<NR_OPEN ; i++)
 328                 if (current->filp[i])
 329                         sys_close(i);
 330         forget_original_parent(current);
 331         iput(current->pwd);
 332         current->pwd = NULL;
 333         iput(current->root);
 334         current->root = NULL;
 335         iput(current->executable);
 336         current->executable = NULL;
 337         for (i=0; i < current->numlibraries; i++) {
 338                 iput(current->libraries[i].library);
 339                 current->libraries[i].library = NULL;
 340         }       
 341         current->state = TASK_ZOMBIE;
 342         current->exit_code = code;
 343         current->rss = 0;
 344         /* 
 345          * Check to see if any process groups have become orphaned
 346          * as a result of our exiting, and if they have any stopped
 347          * jobs, send them a SIGUP and then a SIGCONT.  (POSIX 3.2.2.2)
 348          *
 349          * Case i: Our father is in a different pgrp than we are
 350          * and we were the only connection outside, so our pgrp
 351          * is about to become orphaned.
 352          */
 353         if ((current->p_pptr->pgrp != current->pgrp) &&
 354             (current->p_pptr->session == current->session) &&
 355             is_orphaned_pgrp(current->pgrp) &&
 356             has_stopped_jobs(current->pgrp)) {
 357                 kill_pg(current->pgrp,SIGHUP,1);
 358                 kill_pg(current->pgrp,SIGCONT,1);
 359         }
 360         /* Let father know we died */
 361         send_sig (SIGCHLD, current->p_pptr, 1);
 362         
 363         /*
 364          * This loop does two things:
 365          * 
 366          * A.  Make init inherit all the child processes
 367          * B.  Check to see if any process groups have become orphaned
 368          *      as a result of our exiting, and if they have any stopped
 369          *      jobs, send them a SIGHUP and then a SIGCONT.  (POSIX 3.2.2.2)
 370          */
 371         while (p = current->p_cptr) {
 372                 current->p_cptr = p->p_osptr;
 373                 p->p_ysptr = NULL;
 374                 p->flags &= ~PF_PTRACED;
 375                 if (task[1])
 376                         p->p_pptr = task[1];
 377                 else
 378                         p->p_pptr = task[0];
 379                 p->p_osptr = p->p_pptr->p_cptr;
 380                 p->p_osptr->p_ysptr = p;
 381                 p->p_pptr->p_cptr = p;
 382                 if (p->state == TASK_ZOMBIE)
 383                         send_sig(SIGCHLD,p->p_pptr,1);
 384                 /*
 385                  * process group orphan check
 386                  * Case ii: Our child is in a different pgrp 
 387                  * than we are, and it was the only connection
 388                  * outside, so the child pgrp is now orphaned.
 389                  */
 390                 if ((p->pgrp != current->pgrp) &&
 391                     (p->session == current->session) &&
 392                     is_orphaned_pgrp(p->pgrp) &&
 393                     has_stopped_jobs(p->pgrp)) {
 394                         kill_pg(p->pgrp,SIGHUP,1);
 395                         kill_pg(p->pgrp,SIGCONT,1);
 396                 }
 397         }
 398         if (current->leader) {
 399                 struct task_struct **p;
 400                 struct tty_struct *tty;
 401 
 402                 if (current->tty >= 0) {
 403                         tty = TTY_TABLE(current->tty);
 404                         if (tty->pgrp > 0)
 405                                 kill_pg(tty->pgrp, SIGHUP, 1);
 406                         tty->pgrp = -1;
 407                         tty->session = 0;
 408                 }
 409                 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
 410                         if (*p && (*p)->session == current->session)
 411                                 (*p)->tty = -1;
 412         }
 413         if (last_task_used_math == current)
 414                 last_task_used_math = NULL;
 415 #ifdef DEBUG_PROC_TREE
 416         audit_ptree();
 417 #endif
 418         schedule();
 419 /*
 420  * In order to get rid of the "volatile function does return" message
 421  * I did this little loop that confuses gcc to think do_exit really
 422  * is volatile. In fact it's schedule() that is volatile in some
 423  * circumstances: when current->state = ZOMBIE, schedule() never
 424  * returns.
 425  *
 426  * In fact the natural way to do all this is to have the label and the
 427  * goto right after each other, but I put the fake_volatile label at
 428  * the start of the function just in case something /really/ bad
 429  * happens, and the schedule returns. This way we can try again. I'm
 430  * not paranoid: it's just that everybody is out to get me.
 431  */
 432         goto fake_volatile;
 433 }
 434 
 435 int sys_exit(int error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 436 {
 437         do_exit((error_code&0xff)<<8);
 438 }
 439 
 440 int sys_wait4(pid_t pid,unsigned long * stat_addr, int options, struct rusage * ru)
     /* [previous][next][first][last][top][bottom][index][help] */
 441 {
 442         int flag;
 443         struct task_struct *p;
 444         unsigned long oldblocked;
 445 
 446         if (stat_addr)
 447                 verify_area(stat_addr,4);
 448 repeat:
 449         current->signal &= ~(1<<(SIGCHLD-1));
 450         flag=0;
 451         for (p = current->p_cptr ; p ; p = p->p_osptr) {
 452                 if (pid>0) {
 453                         if (p->pid != pid)
 454                                 continue;
 455                 } else if (!pid) {
 456                         if (p->pgrp != current->pgrp)
 457                                 continue;
 458                 } else if (pid != -1) {
 459                         if (p->pgrp != -pid)
 460                                 continue;
 461                 }
 462                 switch (p->state) {
 463                         case TASK_STOPPED:
 464                                 if (!p->exit_code)
 465                                         continue;
 466                                 if (!(options & WUNTRACED) && !(p->flags & PF_PTRACED))
 467                                         continue;
 468                                 if (stat_addr)
 469                                         put_fs_long((p->exit_code << 8) | 0x7f,
 470                                                 stat_addr);
 471                                 p->exit_code = 0;
 472                                 if (ru != NULL)
 473                                         getrusage(p, RUSAGE_BOTH, ru);
 474                                 return p->pid;
 475                         case TASK_ZOMBIE:
 476                                 current->cutime += p->utime + p->cutime;
 477                                 current->cstime += p->stime + p->cstime;
 478                                 current->cmin_flt += p->min_flt + p->cmin_flt;
 479                                 current->cmaj_flt += p->maj_flt + p->cmaj_flt;
 480                                 if (ru != NULL)
 481                                         getrusage(p, RUSAGE_BOTH, ru);
 482                                 flag = p->pid;
 483                                 if (stat_addr)
 484                                         put_fs_long(p->exit_code, stat_addr);
 485                                 if (p->p_opptr != p->p_pptr) {
 486                                         REMOVE_LINKS(p);
 487                                         p->p_pptr = p->p_opptr;
 488                                         SET_LINKS(p);
 489                                         send_sig(SIGCHLD,p->p_pptr,1);
 490                                 } else
 491                                         release(p);
 492 #ifdef DEBUG_PROC_TREE
 493                                 audit_ptree();
 494 #endif
 495                                 return flag;
 496                         default:
 497                                 flag=1;
 498                                 continue;
 499                 }
 500         }
 501         if (flag) {
 502                 if (options & WNOHANG)
 503                         return 0;
 504                 current->state=TASK_INTERRUPTIBLE;
 505                 oldblocked = current->blocked;
 506                 current->blocked &= ~(1<<(SIGCHLD-1));
 507                 schedule();
 508                 current->blocked = oldblocked;
 509                 if (current->signal & ~(current->blocked | (1<<(SIGCHLD-1))))
 510                         return -ERESTARTSYS;
 511                 else
 512                         goto repeat;
 513         }
 514         return -ECHILD;
 515 }
 516 
 517 /*
 518  * sys_waitpid() remains for compatibility. waitpid() should be
 519  * implemented by calling sys_wait4() from libc.a.
 520  */
 521 int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
     /* [previous][next][first][last][top][bottom][index][help] */
 522 {
 523         return sys_wait4(pid, stat_addr, options, NULL);
 524 }

/* [previous][next][first][last][top][bottom][index][help] */