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_proc
  8. sys_kill
  9. is_orphaned_pgrp
  10. has_stopped_jobs
  11. do_exit
  12. sys_exit
  13. sys_waitpid

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

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