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

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