root/kernel/exit.c

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

DEFINITIONS

This source file includes following definitions.
  1. generate
  2. send_sig
  3. notify_parent
  4. release
  5. bad_task_ptr
  6. audit_ptree
  7. session_of_pgrp
  8. kill_pg
  9. kill_sl
  10. kill_proc
  11. sys_kill
  12. is_orphaned_pgrp
  13. has_stopped_jobs
  14. forget_original_parent
  15. __exit_files
  16. exit_files
  17. __exit_fs
  18. exit_fs
  19. __exit_sighand
  20. exit_sighand
  21. exit_mm
  22. exit_notify
  23. do_exit
  24. sys_exit
  25. sys_wait4
  26. sys_waitpid

   1 /*
   2  *  linux/kernel/exit.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 #undef 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 #include <linux/malloc.h>
  18 
  19 #include <asm/segment.h>
  20 extern void sem_exit (void);
  21 extern void acct_process (long exitcode);
  22 extern void kerneld_exit(void);
  23 
  24 int getrusage(struct task_struct *, int, struct rusage *);
  25 
  26 static inline void generate(unsigned long sig, struct task_struct * p)
     /* [previous][next][first][last][top][bottom][index][help] */
  27 {
  28         unsigned long mask = 1 << (sig-1);
  29         struct sigaction * sa = sig + p->sig->action - 1;
  30 
  31         /*
  32          * Optimize away the signal, if it's a signal that can
  33          * be handled immediately (ie non-blocked and untraced)
  34          * and that is ignored (either explicitly or by default)
  35          */
  36         if (!(mask & p->blocked) && !(p->flags & PF_PTRACED)) {
  37                 /* don't bother with ignored signals (but SIGCHLD is special) */
  38                 if (sa->sa_handler == SIG_IGN && sig != SIGCHLD)
  39                         return;
  40                 /* some signals are ignored by default.. (but SIGCONT already did its deed) */
  41                 if ((sa->sa_handler == SIG_DFL) &&
  42                     (sig == SIGCONT || sig == SIGCHLD || sig == SIGWINCH || sig == SIGURG))
  43                         return;
  44         }
  45         p->signal |= mask;
  46         if (p->state == TASK_INTERRUPTIBLE && (p->signal & ~p->blocked))
  47                 wake_up_process(p);
  48 }
  49 
  50 int send_sig(unsigned long sig,struct task_struct * p,int priv)
     /* [previous][next][first][last][top][bottom][index][help] */
  51 {
  52         if (!p || sig > 32)
  53                 return -EINVAL;
  54         if (!priv && ((sig != SIGCONT) || (current->session != p->session)) &&
  55             (current->euid ^ p->euid) && (current->euid ^ p->uid) &&
  56             (current->uid ^ p->euid) && (current->uid ^ p->uid) &&
  57             !suser())
  58                 return -EPERM;
  59         if (!sig)
  60                 return 0;
  61         /*
  62          * Forget it if the process is already zombie'd.
  63          */
  64         if (!p->sig)
  65                 return 0;
  66         if ((sig == SIGKILL) || (sig == SIGCONT)) {
  67                 if (p->state == TASK_STOPPED)
  68                         wake_up_process(p);
  69                 p->exit_code = 0;
  70                 p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) |
  71                                 (1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) );
  72         }
  73         if (sig == SIGSTOP || sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
  74                 p->signal &= ~(1<<(SIGCONT-1));
  75         /* Actually generate the signal */
  76         generate(sig,p);
  77         return 0;
  78 }
  79 
  80 void notify_parent(struct task_struct * tsk)
     /* [previous][next][first][last][top][bottom][index][help] */
  81 {
  82         if (tsk->p_pptr == task[smp_num_cpus])          /* Init */
  83                 tsk->exit_signal = SIGCHLD;
  84         send_sig(tsk->exit_signal, tsk->p_pptr, 1);
  85         wake_up_interruptible(&tsk->p_pptr->wait_chldexit);
  86 }
  87 
  88 void release(struct task_struct * p)
     /* [previous][next][first][last][top][bottom][index][help] */
  89 {
  90         int i;
  91 
  92         if (!p)
  93                 return;
  94         if (p == current) {
  95                 printk("task releasing itself\n");
  96                 return;
  97         }
  98         for (i=1 ; i<NR_TASKS ; i++)
  99                 if (task[i] == p) {
 100                         nr_tasks--;
 101                         task[i] = NULL;
 102                         REMOVE_LINKS(p);
 103                         release_thread(p);
 104                         if (STACK_MAGIC != *(unsigned long *)p->kernel_stack_page)
 105                                 printk(KERN_ALERT "release: %s kernel stack corruption. Aiee\n", p->comm);
 106                         free_kernel_stack(p->kernel_stack_page);
 107                         current->cmin_flt += p->min_flt + p->cmin_flt;
 108                         current->cmaj_flt += p->maj_flt + p->cmaj_flt;
 109                         current->cnswap += p->nswap + p->cnswap;
 110                         kfree(p);
 111                         return;
 112                 }
 113         panic("trying to release non-existent task");
 114 }
 115 
 116 #ifdef DEBUG_PROC_TREE
 117 /*
 118  * Check to see if a task_struct pointer is present in the task[] array
 119  * Return 0 if found, and 1 if not found.
 120  */
 121 int bad_task_ptr(struct task_struct *p)
     /* [previous][next][first][last][top][bottom][index][help] */
 122 {
 123         int     i;
 124 
 125         if (!p)
 126                 return 0;
 127         for (i=0 ; i<NR_TASKS ; i++)
 128                 if (task[i] == p)
 129                         return 0;
 130         return 1;
 131 }
 132         
 133 /*
 134  * This routine scans the pid tree and makes sure the rep invariant still
 135  * holds.  Used for debugging only, since it's very slow....
 136  *
 137  * It looks a lot scarier than it really is.... we're doing nothing more
 138  * than verifying the doubly-linked list found in p_ysptr and p_osptr, 
 139  * and checking it corresponds with the process tree defined by p_cptr and 
 140  * p_pptr;
 141  */
 142 void audit_ptree(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 143 {
 144         int     i;
 145 
 146         for (i=1 ; i<NR_TASKS ; i++) {
 147                 if (!task[i])
 148                         continue;
 149                 if (bad_task_ptr(task[i]->p_pptr))
 150                         printk("Warning, pid %d's parent link is bad\n",
 151                                 task[i]->pid);
 152                 if (bad_task_ptr(task[i]->p_cptr))
 153                         printk("Warning, pid %d's child link is bad\n",
 154                                 task[i]->pid);
 155                 if (bad_task_ptr(task[i]->p_ysptr))
 156                         printk("Warning, pid %d's ys link is bad\n",
 157                                 task[i]->pid);
 158                 if (bad_task_ptr(task[i]->p_osptr))
 159                         printk("Warning, pid %d's os link is bad\n",
 160                                 task[i]->pid);
 161                 if (task[i]->p_pptr == task[i])
 162                         printk("Warning, pid %d parent link points to self\n",
 163                                 task[i]->pid);
 164                 if (task[i]->p_cptr == task[i])
 165                         printk("Warning, pid %d child link points to self\n",
 166                                 task[i]->pid);
 167                 if (task[i]->p_ysptr == task[i])
 168                         printk("Warning, pid %d ys link points to self\n",
 169                                 task[i]->pid);
 170                 if (task[i]->p_osptr == task[i])
 171                         printk("Warning, pid %d os link points to self\n",
 172                                 task[i]->pid);
 173                 if (task[i]->p_osptr) {
 174                         if (task[i]->p_pptr != task[i]->p_osptr->p_pptr)
 175                                 printk(
 176                         "Warning, pid %d older sibling %d parent is %d\n",
 177                                 task[i]->pid, task[i]->p_osptr->pid,
 178                                 task[i]->p_osptr->p_pptr->pid);
 179                         if (task[i]->p_osptr->p_ysptr != task[i])
 180                                 printk(
 181                 "Warning, pid %d older sibling %d has mismatched ys link\n",
 182                                 task[i]->pid, task[i]->p_osptr->pid);
 183                 }
 184                 if (task[i]->p_ysptr) {
 185                         if (task[i]->p_pptr != task[i]->p_ysptr->p_pptr)
 186                                 printk(
 187                         "Warning, pid %d younger sibling %d parent is %d\n",
 188                                 task[i]->pid, task[i]->p_osptr->pid,
 189                                 task[i]->p_osptr->p_pptr->pid);
 190                         if (task[i]->p_ysptr->p_osptr != task[i])
 191                                 printk(
 192                 "Warning, pid %d younger sibling %d has mismatched os link\n",
 193                                 task[i]->pid, task[i]->p_ysptr->pid);
 194                 }
 195                 if (task[i]->p_cptr) {
 196                         if (task[i]->p_cptr->p_pptr != task[i])
 197                                 printk(
 198                         "Warning, pid %d youngest child %d has mismatched parent link\n",
 199                                 task[i]->pid, task[i]->p_cptr->pid);
 200                         if (task[i]->p_cptr->p_ysptr)
 201                                 printk(
 202                         "Warning, pid %d youngest child %d has non-NULL ys link\n",
 203                                 task[i]->pid, task[i]->p_cptr->pid);
 204                 }
 205         }
 206 }
 207 #endif /* DEBUG_PROC_TREE */
 208 
 209 /*
 210  * This checks not only the pgrp, but falls back on the pid if no
 211  * satisfactory pgrp is found. I dunno - gdb doesn't work correctly
 212  * without this...
 213  */
 214 int session_of_pgrp(int pgrp)
     /* [previous][next][first][last][top][bottom][index][help] */
 215 {
 216         struct task_struct *p;
 217         int fallback;
 218 
 219         fallback = -1;
 220         for_each_task(p) {
 221                 if (p->session <= 0)
 222                         continue;
 223                 if (p->pgrp == pgrp)
 224                         return p->session;
 225                 if (p->pid == pgrp)
 226                         fallback = p->session;
 227         }
 228         return fallback;
 229 }
 230 
 231 /*
 232  * kill_pg() sends a signal to a process group: this is what the tty
 233  * control characters do (^C, ^Z etc)
 234  */
 235 int kill_pg(int pgrp, int sig, int priv)
     /* [previous][next][first][last][top][bottom][index][help] */
 236 {
 237         struct task_struct *p;
 238         int err,retval = -ESRCH;
 239         int found = 0;
 240 
 241         if (sig<0 || sig>32 || pgrp<=0)
 242                 return -EINVAL;
 243         for_each_task(p) {
 244                 if (p->pgrp == pgrp) {
 245                         if ((err = send_sig(sig,p,priv)) != 0)
 246                                 retval = err;
 247                         else
 248                                 found++;
 249                 }
 250         }
 251         return(found ? 0 : retval);
 252 }
 253 
 254 /*
 255  * kill_sl() sends a signal to the session leader: this is used
 256  * to send SIGHUP to the controlling process of a terminal when
 257  * the connection is lost.
 258  */
 259 int kill_sl(int sess, int sig, int priv)
     /* [previous][next][first][last][top][bottom][index][help] */
 260 {
 261         struct task_struct *p;
 262         int err,retval = -ESRCH;
 263         int found = 0;
 264 
 265         if (sig<0 || sig>32 || sess<=0)
 266                 return -EINVAL;
 267         for_each_task(p) {
 268                 if (p->session == sess && p->leader) {
 269                         if ((err = send_sig(sig,p,priv)) != 0)
 270                                 retval = err;
 271                         else
 272                                 found++;
 273                 }
 274         }
 275         return(found ? 0 : retval);
 276 }
 277 
 278 int kill_proc(int pid, int sig, int priv)
     /* [previous][next][first][last][top][bottom][index][help] */
 279 {
 280         struct task_struct *p;
 281 
 282         if (sig<0 || sig>32)
 283                 return -EINVAL;
 284         for_each_task(p) {
 285                 if (p && p->pid == pid)
 286                         return send_sig(sig,p,priv);
 287         }
 288         return(-ESRCH);
 289 }
 290 
 291 /*
 292  * POSIX specifies that kill(-1,sig) is unspecified, but what we have
 293  * is probably wrong.  Should make it like BSD or SYSV.
 294  */
 295 asmlinkage int sys_kill(int pid,int sig)
     /* [previous][next][first][last][top][bottom][index][help] */
 296 {
 297         int err, retval = 0, count = 0;
 298 
 299         if (!pid)
 300                 return(kill_pg(current->pgrp,sig,0));
 301         if (pid == -1) {
 302                 struct task_struct * p;
 303                 for_each_task(p) {
 304                         if (p->pid > 1 && p != current) {
 305                                 ++count;
 306                                 if ((err = send_sig(sig,p,0)) != -EPERM)
 307                                         retval = err;
 308                         }
 309                 }
 310                 return(count ? retval : -ESRCH);
 311         }
 312         if (pid < 0) 
 313                 return(kill_pg(-pid,sig,0));
 314         /* Normal kill */
 315         return(kill_proc(pid,sig,0));
 316 }
 317 
 318 /*
 319  * Determine if a process group is "orphaned", according to the POSIX
 320  * definition in 2.2.2.52.  Orphaned process groups are not to be affected
 321  * by terminal-generated stop signals.  Newly orphaned process groups are 
 322  * to receive a SIGHUP and a SIGCONT.
 323  * 
 324  * "I ask you, have you ever known what it is to be an orphan?"
 325  */
 326 int is_orphaned_pgrp(int pgrp)
     /* [previous][next][first][last][top][bottom][index][help] */
 327 {
 328         struct task_struct *p;
 329 
 330         for_each_task(p) {
 331                 if ((p->pgrp != pgrp) || 
 332                     (p->state == TASK_ZOMBIE) ||
 333                     (p->p_pptr->pid == 1))
 334                         continue;
 335                 if ((p->p_pptr->pgrp != pgrp) &&
 336                     (p->p_pptr->session == p->session))
 337                         return 0;
 338         }
 339         return(1);      /* (sighing) "Often!" */
 340 }
 341 
 342 static inline int has_stopped_jobs(int pgrp)
     /* [previous][next][first][last][top][bottom][index][help] */
 343 {
 344         struct task_struct * p;
 345 
 346         for_each_task(p) {
 347                 if (p->pgrp != pgrp)
 348                         continue;
 349                 if (p->state == TASK_STOPPED)
 350                         return(1);
 351         }
 352         return(0);
 353 }
 354 
 355 static inline void forget_original_parent(struct task_struct * father)
     /* [previous][next][first][last][top][bottom][index][help] */
 356 {
 357         struct task_struct * p;
 358 
 359         for_each_task(p) {
 360                 if (p->p_opptr == father)
 361                         if (task[smp_num_cpus]) /* init */
 362                                 p->p_opptr = task[smp_num_cpus];
 363                         else
 364                                 p->p_opptr = task[0];
 365         }
 366 }
 367 
 368 static inline void __exit_files(struct task_struct *tsk)
     /* [previous][next][first][last][top][bottom][index][help] */
 369 {
 370         struct files_struct * files = tsk->files;
 371 
 372         if (files) {
 373                 tsk->files = NULL;
 374                 if (!--files->count) {
 375                         int i;
 376                         for (i=0 ; i<NR_OPEN ; i++) {
 377                                 struct file * filp = files->fd[i];
 378                                 if (!filp)
 379                                         continue;
 380                                 files->fd[i] = NULL;
 381                                 close_fp(filp);
 382                         }
 383                         kfree(files);
 384                 }
 385         }
 386 }
 387 
 388 void exit_files(struct task_struct *tsk)
     /* [previous][next][first][last][top][bottom][index][help] */
 389 {
 390   __exit_files(tsk);
 391 }
 392 
 393 static inline void __exit_fs(struct task_struct *tsk)
     /* [previous][next][first][last][top][bottom][index][help] */
 394 {
 395         struct fs_struct * fs = tsk->fs;
 396 
 397         if (fs) {
 398                 tsk->fs = NULL;
 399                 if (!--fs->count) {
 400                         iput(fs->root);
 401                         iput(fs->pwd);
 402                         kfree(fs);
 403                 }
 404         }
 405 }
 406 
 407 void exit_fs(struct task_struct *tsk)
     /* [previous][next][first][last][top][bottom][index][help] */
 408 {
 409   __exit_fs(tsk);
 410 }
 411 
 412 static inline void __exit_sighand(struct task_struct *tsk)
     /* [previous][next][first][last][top][bottom][index][help] */
 413 {
 414         struct signal_struct * sig = tsk->sig;
 415 
 416         if (sig) {
 417                 tsk->sig = NULL;
 418                 if (!--sig->count) {
 419                         kfree(sig);
 420                 }
 421         }
 422 }
 423 
 424 void exit_sighand(struct task_struct *tsk)
     /* [previous][next][first][last][top][bottom][index][help] */
 425 {
 426   __exit_sighand(tsk);
 427 }
 428 
 429 static inline void exit_mm(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 430 {
 431         struct mm_struct * mm = current->mm;
 432 
 433         current->swappable = 0;
 434         if (mm) {
 435                 if (!--mm->count) {
 436                         exit_mmap(mm);
 437                         free_page_tables(current);
 438                         kfree(mm);
 439                 }
 440                 current->mm = NULL;
 441         }
 442 }
 443 
 444 /* 
 445  * Send signals to all our closest relatives so that they know
 446  * to properly mourn us..
 447  */
 448 static void exit_notify(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 449 {
 450         struct task_struct * p;
 451 
 452         forget_original_parent(current);
 453         /* 
 454          * Check to see if any process groups have become orphaned
 455          * as a result of our exiting, and if they have any stopped
 456          * jobs, send them a SIGHUP and then a SIGCONT.  (POSIX 3.2.2.2)
 457          *
 458          * Case i: Our father is in a different pgrp than we are
 459          * and we were the only connection outside, so our pgrp
 460          * is about to become orphaned.
 461          */
 462         if ((current->p_pptr->pgrp != current->pgrp) &&
 463             (current->p_pptr->session == current->session) &&
 464             is_orphaned_pgrp(current->pgrp) &&
 465             has_stopped_jobs(current->pgrp)) {
 466                 kill_pg(current->pgrp,SIGHUP,1);
 467                 kill_pg(current->pgrp,SIGCONT,1);
 468         }
 469         /* Let father know we died */
 470         notify_parent(current);
 471         
 472         /*
 473          * This loop does two things:
 474          * 
 475          * A.  Make init inherit all the child processes
 476          * B.  Check to see if any process groups have become orphaned
 477          *      as a result of our exiting, and if they have any stopped
 478          *      jobs, send them a SIGHUP and then a SIGCONT.  (POSIX 3.2.2.2)
 479          */
 480         while ((p = current->p_cptr) != NULL) {
 481                 current->p_cptr = p->p_osptr;
 482                 p->p_ysptr = NULL;
 483                 p->flags &= ~(PF_PTRACED|PF_TRACESYS);
 484                 if (task[smp_num_cpus] && task[smp_num_cpus] != current) /* init */
 485                         p->p_pptr = task[smp_num_cpus];
 486                 else
 487                         p->p_pptr = task[0];
 488                 p->p_osptr = p->p_pptr->p_cptr;
 489                 p->p_osptr->p_ysptr = p;
 490                 p->p_pptr->p_cptr = p;
 491                 if (p->state == TASK_ZOMBIE)
 492                         notify_parent(p);
 493                 /*
 494                  * process group orphan check
 495                  * Case ii: Our child is in a different pgrp 
 496                  * than we are, and it was the only connection
 497                  * outside, so the child pgrp is now orphaned.
 498                  */
 499                 if ((p->pgrp != current->pgrp) &&
 500                     (p->session == current->session) &&
 501                     is_orphaned_pgrp(p->pgrp) &&
 502                     has_stopped_jobs(p->pgrp)) {
 503                         kill_pg(p->pgrp,SIGHUP,1);
 504                         kill_pg(p->pgrp,SIGCONT,1);
 505                 }
 506         }
 507         if (current->leader)
 508                 disassociate_ctty(1);
 509 }
 510 
 511 NORET_TYPE void do_exit(long code)
     /* [previous][next][first][last][top][bottom][index][help] */
 512 {
 513         if (intr_count) {
 514                 printk("Aiee, killing interrupt handler\n");
 515                 intr_count = 0;
 516         }
 517 fake_volatile:
 518         acct_process(code);
 519         current->flags |= PF_EXITING;
 520         del_timer(&current->real_timer);
 521         sem_exit();
 522         kerneld_exit();
 523         exit_mm();
 524         __exit_files(current);
 525         __exit_fs(current);
 526         __exit_sighand(current);
 527         exit_thread();
 528         current->state = TASK_ZOMBIE;
 529         current->exit_code = code;
 530         exit_notify();
 531 #ifdef DEBUG_PROC_TREE
 532         audit_ptree();
 533 #endif
 534         if (current->exec_domain && current->exec_domain->use_count)
 535                 (*current->exec_domain->use_count)--;
 536         if (current->binfmt && current->binfmt->use_count)
 537                 (*current->binfmt->use_count)--;
 538         schedule();
 539 /*
 540  * In order to get rid of the "volatile function does return" message
 541  * I did this little loop that confuses gcc to think do_exit really
 542  * is volatile. In fact it's schedule() that is volatile in some
 543  * circumstances: when current->state = ZOMBIE, schedule() never
 544  * returns.
 545  *
 546  * In fact the natural way to do all this is to have the label and the
 547  * goto right after each other, but I put the fake_volatile label at
 548  * the start of the function just in case something /really/ bad
 549  * happens, and the schedule returns. This way we can try again. I'm
 550  * not paranoid: it's just that everybody is out to get me.
 551  */
 552         goto fake_volatile;
 553 }
 554 
 555 asmlinkage int sys_exit(int error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 556 {
 557         do_exit((error_code&0xff)<<8);
 558 }
 559 
 560 asmlinkage int sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru)
     /* [previous][next][first][last][top][bottom][index][help] */
 561 {
 562         int flag, retval;
 563         struct wait_queue wait = { current, NULL };
 564         struct task_struct *p;
 565 
 566         if (stat_addr) {
 567                 flag = verify_area(VERIFY_WRITE, stat_addr, sizeof(*stat_addr));
 568                 if (flag)
 569                         return flag;
 570         }
 571         if (ru) {
 572                 flag = verify_area(VERIFY_WRITE, ru, sizeof(*ru));
 573                 if (flag)
 574                         return flag;
 575         }
 576         add_wait_queue(&current->wait_chldexit,&wait);
 577 repeat:
 578         flag=0;
 579         for (p = current->p_cptr ; p ; p = p->p_osptr) {
 580                 if (pid>0) {
 581                         if (p->pid != pid)
 582                                 continue;
 583                 } else if (!pid) {
 584                         if (p->pgrp != current->pgrp)
 585                                 continue;
 586                 } else if (pid != -1) {
 587                         if (p->pgrp != -pid)
 588                                 continue;
 589                 }
 590                 /* wait for cloned processes iff the __WCLONE flag is set */
 591                 if ((p->exit_signal != SIGCHLD) ^ ((options & __WCLONE) != 0))
 592                         continue;
 593                 flag = 1;
 594                 switch (p->state) {
 595                         case TASK_STOPPED:
 596                                 if (!p->exit_code)
 597                                         continue;
 598                                 if (!(options & WUNTRACED) && !(p->flags & PF_PTRACED))
 599                                         continue;
 600                                 if (ru != NULL)
 601                                         getrusage(p, RUSAGE_BOTH, ru);
 602                                 if (stat_addr)
 603                                         put_user((p->exit_code << 8) | 0x7f,
 604                                                 stat_addr);
 605                                 p->exit_code = 0;
 606                                 retval = p->pid;
 607                                 goto end_wait4;
 608                         case TASK_ZOMBIE:
 609                                 current->cutime += p->utime + p->cutime;
 610                                 current->cstime += p->stime + p->cstime;
 611                                 if (ru != NULL)
 612                                         getrusage(p, RUSAGE_BOTH, ru);
 613                                 if (stat_addr)
 614                                         put_user(p->exit_code, stat_addr);
 615                                 retval = p->pid;
 616                                 if (p->p_opptr != p->p_pptr) {
 617                                         REMOVE_LINKS(p);
 618                                         p->p_pptr = p->p_opptr;
 619                                         SET_LINKS(p);
 620                                         notify_parent(p);
 621                                 } else
 622                                         release(p);
 623 #ifdef DEBUG_PROC_TREE
 624                                 audit_ptree();
 625 #endif
 626                                 goto end_wait4;
 627                         default:
 628                                 continue;
 629                 }
 630         }
 631         if (flag) {
 632                 retval = 0;
 633                 if (options & WNOHANG)
 634                         goto end_wait4;
 635                 current->state=TASK_INTERRUPTIBLE;
 636                 schedule();
 637                 current->signal &= ~(1<<(SIGCHLD-1));
 638                 retval = -ERESTARTSYS;
 639                 if (current->signal & ~current->blocked)
 640                         goto end_wait4;
 641                 goto repeat;
 642         }
 643         retval = -ECHILD;
 644 end_wait4:
 645         remove_wait_queue(&current->wait_chldexit,&wait);
 646         return retval;
 647 }
 648 
 649 #ifndef __alpha__
 650 
 651 /*
 652  * sys_waitpid() remains for compatibility. waitpid() should be
 653  * implemented by calling sys_wait4() from libc.a.
 654  */
 655 asmlinkage int sys_waitpid(pid_t pid,unsigned int * stat_addr, int options)
     /* [previous][next][first][last][top][bottom][index][help] */
 656 {
 657         return sys_wait4(pid, stat_addr, options, NULL);
 658 }
 659 
 660 #endif

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