Diff for /linux/kernel/exit.c between versions 1.1.1.6 and 1.1.1.11

version 1.1.1.6, 2018/04/24 18:05:29 version 1.1.1.11, 2018/04/24 18:13:04
Line 1 Line 1
 /*  /*
  *  linux/kernel/exit.c   *  linux/kernel/exit.c
  *   *
  *  (C) 1991  Linus Torvalds   *  Copyright (C) 1991, 1992  Linus Torvalds
  */   */
   
 #define DEBUG_PROC_TREE  #define DEBUG_PROC_TREE
   
 #include <errno.h>  #include <linux/wait.h>
 #include <signal.h>  #include <linux/errno.h>
 #include <sys/wait.h>  #include <linux/signal.h>
   
 #include <linux/sched.h>  #include <linux/sched.h>
 #include <linux/kernel.h>  #include <linux/kernel.h>
   #include <linux/mm.h>
 #include <linux/tty.h>  #include <linux/tty.h>
   
 #include <asm/segment.h>  #include <asm/segment.h>
   
 int sys_close(int fd);  int sys_close(int fd);
   
 inline int send_sig(long sig,struct task_struct * p,int priv)  int send_sig(long sig,struct task_struct * p,int priv)
 {  {
         if (!p || (sig < 0) || (sig > 32))          if (!p || (sig < 0) || (sig > 32))
                 return -EINVAL;                  return -EINVAL;
         if (!priv && (current->euid!=p->euid) && !suser())          if (!priv && ((sig != SIGCONT) || (current->session != p->session)) &&
               (current->euid != p->euid) && (current->uid != p->uid) && !suser())
                 return -EPERM;                  return -EPERM;
         if (!sig)          if (!sig)
                 return 0;                  return 0;
Line 41  inline int send_sig(long sig,struct task Line 43  inline int send_sig(long sig,struct task
                 /* save the signal number for wait. */                  /* save the signal number for wait. */
                 p->exit_code = sig;                  p->exit_code = sig;
   
                 /* we have to make sure the parent is awake. */                  /* we have to make sure the parent process is awake. */
                 if (p->p_pptr != NULL && p->p_pptr->state == TASK_INTERRUPTIBLE)                  if (p->p_pptr != NULL && p->p_pptr->state == TASK_INTERRUPTIBLE)
                         p->p_pptr->state = TASK_RUNNING;                          p->p_pptr->state = TASK_RUNNING;
   
                 /* we have to make sure that the process stops. */                  /* we have to make sure that the process stops. */
                 if (p->state == TASK_INTERRUPTIBLE || p->state == TASK_RUNNING)                  if (p->state == TASK_INTERRUPTIBLE || p->state == TASK_RUNNING)
                         p->state = TASK_STOPPED;                          p->state = TASK_STOPPED;
   
                 if (p == current)  
                         schedule();  
         }          }
         return 0;          return 0;
 }  }
Line 66  void release(struct task_struct * p) Line 65  void release(struct task_struct * p)
                 return;                  return;
         }          }
         for (i=1 ; i<NR_TASKS ; i++)          for (i=1 ; i<NR_TASKS ; i++)
                 if (task[i]==p) {                  if (task[i] == p) {
                         task[i]=NULL;                          task[i] = NULL;
                         /* Update links */                          REMOVE_LINKS(p);
                         if (p->p_osptr)                          free_page((long) p);
                                 p->p_osptr->p_ysptr = p->p_ysptr;  
                         if (p->p_ysptr)  
                                 p->p_ysptr->p_osptr = p->p_osptr;  
                         else  
                                 p->p_pptr->p_cptr = p->p_osptr;  
                         free_page((long)p);  
                         schedule();  
                         return;                          return;
                 }                  }
         panic("trying to release non-existent task");          panic("trying to release non-existent task");
Line 171  void audit_ptree() Line 163  void audit_ptree()
 }  }
 #endif /* DEBUG_PROC_TREE */  #endif /* DEBUG_PROC_TREE */
   
   /*
    * This checks not only the pgrp, but falls back on the pid if no
    * satisfactory prgp is found. I dunno - gdb doesn't work correctly
    * without this...
    */
 int session_of_pgrp(int pgrp)  int session_of_pgrp(int pgrp)
 {  {
         struct task_struct **p;          struct task_struct **p;
           int fallback;
   
         for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)          fallback = -1;
           for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
                   if (!*p || (*p)->session <= 0)
                           continue;
                 if ((*p)->pgrp == pgrp)                  if ((*p)->pgrp == pgrp)
                         return((*p)->session);                          return (*p)->session;
         return -1;                  if ((*p)->pid == pgrp)
                           fallback = (*p)->session;
           }
           return fallback;
 }  }
   
 int kill_pg(int pgrp, int sig, int priv)  int kill_pg(int pgrp, int sig, int priv)
Line 190  int kill_pg(int pgrp, int sig, int priv) Line 194  int kill_pg(int pgrp, int sig, int priv)
         if (sig<0 || sig>32 || pgrp<=0)          if (sig<0 || sig>32 || pgrp<=0)
                 return -EINVAL;                  return -EINVAL;
         for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)          for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
                 if ((*p)->pgrp == pgrp) {                  if (*p && (*p)->pgrp == pgrp) {
                         if (sig && (err = send_sig(sig,*p,priv)))                          if (sig && (err = send_sig(sig,*p,priv)))
                                 retval = err;                                  retval = err;
                         else                          else
Line 206  int kill_proc(int pid, int sig, int priv Line 210  int kill_proc(int pid, int sig, int priv
         if (sig<0 || sig>32)          if (sig<0 || sig>32)
                 return -EINVAL;                  return -EINVAL;
         for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)          for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
                 if ((*p)->pid == pid)                  if (*p && (*p)->pid == pid)
                         return(sig ? send_sig(sig,*p,priv) : 0);                          return(sig ? send_sig(sig,*p,priv) : 0);
         return(-ESRCH);          return(-ESRCH);
 }  }
Line 218  int kill_proc(int pid, int sig, int priv Line 222  int kill_proc(int pid, int sig, int priv
 int sys_kill(int pid,int sig)  int sys_kill(int pid,int sig)
 {  {
         struct task_struct **p = NR_TASKS + task;          struct task_struct **p = NR_TASKS + task;
         int err, retval = 0;          int err, retval = 0, count = 0;
   
         if (!pid)          if (!pid)
                 return(kill_pg(current->pid,sig,0));                  return(kill_pg(current->pgrp,sig,0));
         if (pid == -1) {          if (pid == -1) {
                 while (--p > &FIRST_TASK)                  while (--p > &FIRST_TASK)
                         if (err = send_sig(sig,*p,0))                          if (*p && (*p)->pid > 1 && *p != current) {
                                 retval = err;                                  ++count;
                 return(retval);                                  if ((err = send_sig(sig,*p,0)) != -EPERM)
                                           retval = err;
                           }
                   return(count ? retval : -ESRCH);
         }          }
         if (pid < 0)           if (pid < 0) 
                 return(kill_pg(-pid,sig,0));                  return(kill_pg(-pid,sig,0));
Line 264  static int has_stopped_jobs(int pgrp) Line 271  static int has_stopped_jobs(int pgrp)
         struct task_struct ** p;          struct task_struct ** p;
   
         for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {          for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
                 if ((*p)->pgrp != pgrp)                  if (!*p || (*p)->pgrp != pgrp)
                         continue;                          continue;
                 if ((*p)->state == TASK_STOPPED)                  if ((*p)->state == TASK_STOPPED)
                         return(1);                          return(1);
Line 272  static int has_stopped_jobs(int pgrp) Line 279  static int has_stopped_jobs(int pgrp)
         return(0);          return(0);
 }  }
   
   static void forget_original_parent(struct task_struct * father)
   {
           struct task_struct ** p;
   
           for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
                   if (*p && (*p)->p_opptr == father)
                           if (task[1])
                                   (*p)->p_opptr = task[1];
                           else
                                   (*p)->p_opptr = task[0];
   }
   
 volatile void do_exit(long code)  volatile void do_exit(long code)
 {  {
         struct task_struct *p;          struct task_struct *p;
         int i;          int i;
   
   fake_volatile:
         free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));          free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
         free_page_tables(get_base(current->ldt[2]),get_limit(0x17));          free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
         for (i=0 ; i<NR_OPEN ; i++)          for (i=0 ; i<NR_OPEN ; i++)
                 if (current->filp[i])                  if (current->filp[i])
                         sys_close(i);                          sys_close(i);
           forget_original_parent(current);
         iput(current->pwd);          iput(current->pwd);
         current->pwd = NULL;          current->pwd = NULL;
         iput(current->root);          iput(current->root);
         current->root = NULL;          current->root = NULL;
         iput(current->executable);          iput(current->executable);
         current->executable = NULL;          current->executable = NULL;
         iput(current->library);          for (i=0; i < current->numlibraries; i++) {
         current->library = NULL;                  iput(current->libraries[i].library);
                   current->libraries[i].library = NULL;
           }       
         current->state = TASK_ZOMBIE;          current->state = TASK_ZOMBIE;
         current->exit_code = code;          current->exit_code = code;
           current->rss = 0;
         /*           /* 
          * Check to see if any process groups have become orphaned           * Check to see if any process groups have become orphaned
          * as a result of our exiting, and if they have any stopped           * as a result of our exiting, and if they have any stopped
Line 317  volatile void do_exit(long code) Line 341  volatile void do_exit(long code)
          * A.  Make init inherit all the child processes           * A.  Make init inherit all the child processes
          * B.  Check to see if any process groups have become orphaned           * B.  Check to see if any process groups have become orphaned
          *      as a result of our exiting, and if they have any stopped           *      as a result of our exiting, and if they have any stopped
          *      jons, send them a SIGUP and then a SIGCONT.  (POSIX 3.2.2.2)           *      jobs, send them a SIGHUP and then a SIGCONT.  (POSIX 3.2.2.2)
          */           */
         if (p = current->p_cptr) {          while (p = current->p_cptr) {
                 while (1) {                  current->p_cptr = p->p_osptr;
                         p->flags &= ~PF_PTRACED;                  p->p_ysptr = NULL;
                   p->flags &= ~PF_PTRACED;
                   if (task[1])
                         p->p_pptr = task[1];                          p->p_pptr = task[1];
                         if (p->state == TASK_ZOMBIE)                  else
                                 task[1]->signal |= (1<<(SIGCHLD-1));                          p->p_pptr = task[0];
                         /*                  p->p_osptr = p->p_pptr->p_cptr;
                          * process group orphan check                  p->p_osptr->p_ysptr = p;
                          * Case ii: Our child is in a different pgrp                   p->p_pptr->p_cptr = p;
                          * than we are, and it was the only connection                  if (p->state == TASK_ZOMBIE)
                          * outside, so the child pgrp is now orphaned.                          send_sig(SIGCHLD,p->p_pptr,1);
                          */                  /*
                         if ((p->pgrp != current->pgrp) &&                   * process group orphan check
                             (p->session == current->session) &&                   * Case ii: Our child is in a different pgrp 
                             is_orphaned_pgrp(p->pgrp) &&                   * than we are, and it was the only connection
                             has_stopped_jobs(p->pgrp)) {                   * outside, so the child pgrp is now orphaned.
                                 kill_pg(p->pgrp,SIGHUP,1);                   */
                                 kill_pg(p->pgrp,SIGCONT,1);                  if ((p->pgrp != current->pgrp) &&
                         }                      (p->session == current->session) &&
                         if (p->p_osptr) {                      is_orphaned_pgrp(p->pgrp) &&
                                 p = p->p_osptr;                      has_stopped_jobs(p->pgrp)) {
                                 continue;                          kill_pg(p->pgrp,SIGHUP,1);
                         }                          kill_pg(p->pgrp,SIGCONT,1);
                         /*  
                          * This is it; link everything into init's children   
                          * and leave   
                          */  
                         p->p_osptr = task[1]->p_cptr;  
                         task[1]->p_cptr->p_ysptr = p;  
                         task[1]->p_cptr = current->p_cptr;  
                         current->p_cptr = 0;  
                         break;  
                 }                  }
         }          }
         if (current->leader) {          if (current->leader) {
Line 365  volatile void do_exit(long code) Line 382  volatile void do_exit(long code)
                         tty->session = 0;                          tty->session = 0;
                 }                  }
                 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)                  for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
                         if ((*p)->session == current->session)                          if (*p && (*p)->session == current->session)
                                 (*p)->tty = -1;                                  (*p)->tty = -1;
         }          }
         if (last_task_used_math == current)          if (last_task_used_math == current)
Line 374  volatile void do_exit(long code) Line 391  volatile void do_exit(long code)
         audit_ptree();          audit_ptree();
 #endif  #endif
         schedule();          schedule();
   /*
    * In order to get rid of the "volatile function does return" message
    * I did this little loop that confuses gcc to think do_exit really
    * is volatile. In fact it's schedule() that is volatile in some
    * circumstances: when current->state = ZOMBIE, schedule() never
    * returns.
    *
    * In fact the natural way to do all this is to have the label and the
    * goto right after each other, but I put the fake_volatile label at
    * the start of the function just in case something /really/ bad
    * happens, and the schedule returns. This way we can try again. I'm
    * not paranoid: it's just that everybody is out to get me.
    */
           goto fake_volatile;
 }  }
   
 int sys_exit(int error_code)  int sys_exit(int error_code)
Line 390  int sys_waitpid(pid_t pid,unsigned long  Line 421  int sys_waitpid(pid_t pid,unsigned long 
         if (stat_addr)          if (stat_addr)
                 verify_area(stat_addr,4);                  verify_area(stat_addr,4);
 repeat:  repeat:
           current->signal &= ~(1<<(SIGCHLD-1));
         flag=0;          flag=0;
         for (p = current->p_cptr ; p ; p = p->p_osptr) {          for (p = current->p_cptr ; p ; p = p->p_osptr) {
                 if (pid>0) {                  if (pid>0) {
                         if (p->pid != pid)                          if (p->pid != pid)
                                 continue;                                  continue;
Line 404  repeat: Line 436  repeat:
                 }                  }
                 switch (p->state) {                  switch (p->state) {
                         case TASK_STOPPED:                          case TASK_STOPPED:
                                 if (!(options & WUNTRACED) ||                                   if (!p->exit_code)
                                     !p->exit_code)                                          continue;
                                   if (!(options & WUNTRACED) && !(p->flags & PF_PTRACED))
                                         continue;                                          continue;
                                 if (stat_addr)                                  if (stat_addr)
                                         put_fs_long((p->exit_code << 8) | 0x7f,                                          put_fs_long((p->exit_code << 8) | 0x7f,
Line 413  repeat: Line 446  repeat:
                                 p->exit_code = 0;                                  p->exit_code = 0;
                                 return p->pid;                                  return p->pid;
                         case TASK_ZOMBIE:                          case TASK_ZOMBIE:
                                 current->cutime += p->utime;                                  current->cutime += p->utime + p->cutime;
                                 current->cstime += p->stime;                                  current->cstime += p->stime + p->cstime;
                                   current->cmin_flt += p->min_flt + p->cmin_flt;
                                   current->cmaj_flt += p->maj_flt + p->cmaj_flt;
                                 flag = p->pid;                                  flag = p->pid;
                                 if (stat_addr)                                  if (stat_addr)
                                         put_fs_long(p->exit_code, stat_addr);                                          put_fs_long(p->exit_code, stat_addr);
                                 release(p);                                  if (p->p_opptr != p->p_pptr) {
                                           REMOVE_LINKS(p);
                                           p->p_pptr = p->p_opptr;
                                           SET_LINKS(p);
                                           send_sig(SIGCHLD,p->p_pptr,1);
                                   } else
                                           release(p);
 #ifdef DEBUG_PROC_TREE  #ifdef DEBUG_PROC_TREE
                                 audit_ptree();                                  audit_ptree();
 #endif  #endif
Line 443  repeat: Line 484  repeat:
         }          }
         return -ECHILD;          return -ECHILD;
 }  }
   
   

Removed from v.1.1.1.6  
changed lines
  Added in v.1.1.1.11


unix.superglobalmegacorp.com