Diff for /linux/kernel/exit.c between versions 1.1.1.4 and 1.1.1.8

version 1.1.1.4, 2018/04/24 18:03:15 version 1.1.1.8, 2018/04/24 18:07:55
Line 15 Line 15
 #include <linux/tty.h>  #include <linux/tty.h>
 #include <asm/segment.h>  #include <asm/segment.h>
   
 int sys_pause(void);  
 int sys_close(int fd);  int sys_close(int fd);
   
   int send_sig(long sig,struct task_struct * p,int priv)
   {
           if (!p || (sig < 0) || (sig > 32))
                   return -EINVAL;
           if (!priv && ((sig != SIGCONT) || (current->session != p->session)) &&
               (current->euid != p->euid) && !suser())
                   return -EPERM;
           if (!sig)
                   return 0;
           if ((sig == SIGKILL) || (sig == SIGCONT)) {
                   if (p->state == TASK_STOPPED)
                           p->state = TASK_RUNNING;
                   p->exit_code = 0;
                   p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) |
                                   (1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) );
           } 
           /* Depends on order SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU */
           if ((sig >= SIGSTOP) && (sig <= SIGTTOU)) 
                   p->signal &= ~(1<<(SIGCONT-1));
           /* Actually deliver the signal */
           p->signal |= (1<<(sig-1));
           if (p->flags & PF_PTRACED) {
                   /* save the signal number for wait. */
                   p->exit_code = sig;
   
                   /* we have to make sure the parent is awake. */
                   if (p->p_pptr != NULL && p->p_pptr->state == TASK_INTERRUPTIBLE)
                           p->p_pptr->state = TASK_RUNNING;
   
                   /* we have to make sure that the process stops. */
                   if (p->state == TASK_INTERRUPTIBLE || p->state == TASK_RUNNING)
                           p->state = TASK_STOPPED;
           }
           return 0;
   }
   
 void release(struct task_struct * p)  void release(struct task_struct * p)
 {  {
         int i;          int i;
Line 29  void release(struct task_struct * p) Line 64  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 */                          /* Update links */
                         if (p->p_osptr)                          if (p->p_osptr)
                                 p->p_osptr->p_ysptr = p->p_ysptr;                                  p->p_osptr->p_ysptr = p->p_ysptr;
Line 38  void release(struct task_struct * p) Line 73  void release(struct task_struct * p)
                                 p->p_ysptr->p_osptr = p->p_osptr;                                  p->p_ysptr->p_osptr = p->p_osptr;
                         else                          else
                                 p->p_pptr->p_cptr = p->p_osptr;                                  p->p_pptr->p_cptr = p->p_osptr;
                         free_page((long)p);                          free_page((long) p);
                         schedule();  
                         return;                          return;
                 }                  }
         panic("trying to release non-existent task");          panic("trying to release non-existent task");
Line 134  void audit_ptree() Line 168  void audit_ptree()
 }  }
 #endif /* DEBUG_PROC_TREE */  #endif /* DEBUG_PROC_TREE */
   
 static inline int send_sig(long sig,struct task_struct * p,int priv)  /*
 {   * This checks not only the pgrp, but falls back on the pid if no
         if (!p)   * satisfactory prgp is found. I dunno - gdb doesn't work correctly
                 return -EINVAL;   * without this...
         if (!priv && (current->euid!=p->euid) && !suser())   */
                 return -EPERM;  
         if ((sig == SIGKILL) || (sig == SIGCONT)) {  
                 if (p->state == TASK_STOPPED)  
                         p->state = TASK_RUNNING;  
                 p->exit_code = 0;  
                 p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) |  
                                 (1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) );  
         }   
         /* If the signal will be ignored, don't even post it */  
         if ((int) p->sigaction[sig-1].sa_handler == 1)  
                 return 0;  
         /* Depends on order SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU */  
         if ((sig >= SIGSTOP) && (sig <= SIGTTOU))   
                 p->signal &= ~(1<<(SIGCONT-1));  
         /* Actually deliver the signal */  
         p->signal |= (1<<(sig-1));  
         return 0;  
 }  
   
 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 174  int kill_pg(int pgrp, int sig, int priv) Line 196  int kill_pg(int pgrp, int sig, int priv)
         int err,retval = -ESRCH;          int err,retval = -ESRCH;
         int found = 0;          int found = 0;
   
         if (sig<1 || 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 190  int kill_proc(int pid, int sig, int priv Line 212  int kill_proc(int pid, int sig, int priv
 {  {
         struct task_struct **p;          struct task_struct **p;
   
         if (sig<1 || 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 205  int kill_proc(int pid, int sig, int priv Line 227  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 251  static int has_stopped_jobs(int pgrp) Line 276  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 275  volatile void do_exit(long code) Line 300  volatile void do_exit(long code)
         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 296  volatile void do_exit(long code) Line 324  volatile void do_exit(long code)
                 kill_pg(current->pgrp,SIGCONT,1);                  kill_pg(current->pgrp,SIGCONT,1);
         }          }
         /* Let father know we died */          /* Let father know we died */
         current->p_pptr->signal |= (1<<(SIGCHLD-1));          send_sig (SIGCHLD, current->p_pptr, 1);
                   
         /*          /*
          * This loop does two things:           * This loop does two things:
Line 306  volatile void do_exit(long code) Line 334  volatile void do_exit(long code)
          *      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)           *      jons, send them a SIGUP 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->p_pptr = task[1];                  p->p_ysptr = NULL;
                         if (p->state == TASK_ZOMBIE)                  p->flags &= ~PF_PTRACED;
                                 task[1]->signal |= (1<<(SIGCHLD-1));                  p->p_pptr = task[1];
                         /*                  p->p_osptr = task[1]->p_cptr;
                          * process group orphan check                  task[1]->p_cptr->p_ysptr = p;
                          * Case ii: Our child is in a different pgrp                   task[1]->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.                          task[1]->signal |= (1<<(SIGCHLD-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 345  volatile void do_exit(long code) Line 364  volatile void do_exit(long code)
   
                 if (current->tty >= 0) {                  if (current->tty >= 0) {
                         tty = TTY_TABLE(current->tty);                          tty = TTY_TABLE(current->tty);
                         if (tty->pgrp>0)                          if (tty->pgrp > 0)
                                 kill_pg(tty->pgrp, SIGHUP, 1);                                  kill_pg(tty->pgrp, SIGHUP, 1);
                         tty->pgrp = 0;                          tty->pgrp = -1;
                         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 373  int sys_waitpid(pid_t pid,unsigned long  Line 392  int sys_waitpid(pid_t pid,unsigned long 
         struct task_struct *p;          struct task_struct *p;
         unsigned long oldblocked;          unsigned long oldblocked;
   
         verify_area(stat_addr,4);          if (stat_addr)
                   verify_area(stat_addr,4);
 repeat:  repeat:
         flag=0;          flag=0;
         for (p = current->p_cptr ; p ; p = p->p_osptr) {          for (p = current->p_cptr ; p ; p = p->p_osptr) {
Line 389  repeat: Line 409  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;
                                 put_fs_long((p->exit_code << 8) | 0x7f,                                  if (stat_addr)
                                         stat_addr);                                          put_fs_long((p->exit_code << 8) | 0x7f,
                                                   stat_addr);
                                 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;
                                 put_fs_long(p->exit_code, stat_addr);                                  if (stat_addr)
                                           put_fs_long(p->exit_code, stat_addr);
                                 release(p);                                  release(p);
 #ifdef DEBUG_PROC_TREE  #ifdef DEBUG_PROC_TREE
                                 audit_ptree();                                  audit_ptree();

Removed from v.1.1.1.4  
changed lines
  Added in v.1.1.1.8


unix.superglobalmegacorp.com