Roman Rakus 2cb460
			     BASH PATCH REPORT
Roman Rakus 2cb460
			     =================
Roman Rakus 2cb460
Roman Rakus 2cb460
Bash-Release: 3.2
Roman Rakus 2cb460
Patch-ID: bash32-035
Roman Rakus 2cb460
Roman Rakus 2cb460
Bug-Reported-by:	Ingo Molnar <mingo@elte.hu>
Roman Rakus 2cb460
Bug-Reference-ID:	<20071205202901.GA25202@elte.hu>
Roman Rakus 2cb460
Bug-Reference-URL:	http://lists.gnu.org/archive/html/bug-bash/2007-12/msg00014.html
Roman Rakus 2cb460
Roman Rakus 2cb460
Bug-Description:
Roman Rakus 2cb460
Roman Rakus 2cb460
Bash incorrectly puts the second and subsequent children spawned by a
Roman Rakus 2cb460
shell forked to run a command substitution in the wrong process group.
Roman Rakus 2cb460
Roman Rakus 2cb460
Patch:
Roman Rakus 2cb460
Roman Rakus 2cb460
*** ../bash-3.2-patched/subst.c	2007-12-13 22:31:21.000000000 -0500
Roman Rakus 2cb460
--- subst.c	2008-01-17 22:48:15.000000000 -0500
Roman Rakus 2cb460
***************
Roman Rakus 064f29
*** 4622,4628 ****
Roman Rakus 2cb460
  #if defined (JOB_CONTROL)
Roman Rakus 2cb460
    set_sigchld_handler ();
Roman Rakus 2cb460
    stop_making_children ();
Roman Rakus 2cb460
!   pipeline_pgrp = old_pipeline_pgrp;
Roman Rakus 2cb460
  #else
Roman Rakus 2cb460
    stop_making_children ();
Roman Rakus 064f29
  #endif /* JOB_CONTROL */
Roman Rakus 064f29
--- 4622,4629 ----
Roman Rakus 2cb460
  #if defined (JOB_CONTROL)
Roman Rakus 2cb460
    set_sigchld_handler ();
Roman Rakus 2cb460
    stop_making_children ();
Roman Rakus 2cb460
!   if (pid != 0)
Roman Rakus 2cb460
!     pipeline_pgrp = old_pipeline_pgrp;
Roman Rakus 2cb460
  #else
Roman Rakus 2cb460
    stop_making_children ();
Roman Rakus 064f29
  #endif /* JOB_CONTROL */
Roman Rakus 2cb460
*** ../bash-3.2-patched/jobs.c	2007-08-25 13:46:59.000000000 -0400
Roman Rakus 2cb460
--- jobs.c	2007-12-08 16:47:43.000000000 -0500
Roman Rakus 2cb460
***************
Roman Rakus 2cb460
*** 251,254 ****
Roman Rakus 2cb460
--- 251,255 ----
Roman Rakus 2cb460
  static int set_job_status_and_cleanup __P((int));
Roman Rakus 2cb460
  
Roman Rakus 2cb460
+ static WAIT job_signal_status __P((int));
Roman Rakus 2cb460
  static WAIT raw_job_exit_status __P((int));
Roman Rakus 2cb460
  
Roman Rakus 2cb460
***************
Roman Rakus 2cb460
*** 2220,2223 ****
Roman Rakus 2cb460
--- 2238,2261 ----
Roman Rakus 2cb460
  }
Roman Rakus 2cb460
  
Roman Rakus 2cb460
+ static WAIT
Roman Rakus 2cb460
+ job_signal_status (job)
Roman Rakus 2cb460
+      int job;
Roman Rakus 2cb460
+ {
Roman Rakus 2cb460
+   register PROCESS *p;
Roman Rakus 2cb460
+   WAIT s;
Roman Rakus 2cb460
+ 
Roman Rakus 2cb460
+   p = jobs[job]->pipe;
Roman Rakus 2cb460
+   do
Roman Rakus 2cb460
+     {
Roman Rakus 2cb460
+       s = p->status;
Roman Rakus 2cb460
+       if (WIFSIGNALED(s) || WIFSTOPPED(s))
Roman Rakus 2cb460
+ 	break;
Roman Rakus 2cb460
+       p = p->next;
Roman Rakus 2cb460
+     }
Roman Rakus 2cb460
+   while (p != jobs[job]->pipe);
Roman Rakus 2cb460
+ 
Roman Rakus 2cb460
+   return s;
Roman Rakus 2cb460
+ }
Roman Rakus 2cb460
+   
Roman Rakus 2cb460
  /* Return the exit status of the last process in the pipeline for job JOB.
Roman Rakus 2cb460
     This is the exit status of the entire job. */
Roman Rakus 2cb460
***************
Roman Rakus 2cb460
*** 2302,2310 ****
Roman Rakus 2cb460
       received, only if one of the jobs run is killed via SIGINT.  If
Roman Rakus 2cb460
       job control is not set, the job will be run in the same pgrp as
Roman Rakus 2cb460
!      the shell, and the shell will see any signals the job gets. */
Roman Rakus 2cb460
  
Roman Rakus 2cb460
    /* This is possibly a race condition -- should it go in stop_pipeline? */
Roman Rakus 2cb460
    wait_sigint_received = 0;
Roman Rakus 2cb460
!   if (job_control == 0)
Roman Rakus 2cb460
      {
Roman Rakus 2cb460
        old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
Roman Rakus 2cb460
--- 2343,2354 ----
Roman Rakus 2cb460
       received, only if one of the jobs run is killed via SIGINT.  If
Roman Rakus 2cb460
       job control is not set, the job will be run in the same pgrp as
Roman Rakus 2cb460
!      the shell, and the shell will see any signals the job gets.  In
Roman Rakus 2cb460
!      fact, we want this set every time the waiting shell and the waited-
Roman Rakus 2cb460
!      for process are in the same process group, including command
Roman Rakus 2cb460
!      substitution. */
Roman Rakus 2cb460
  
Roman Rakus 2cb460
    /* This is possibly a race condition -- should it go in stop_pipeline? */
Roman Rakus 2cb460
    wait_sigint_received = 0;
Roman Rakus 2cb460
!   if (job_control == 0 || (subshell_environment&SUBSHELL_COMSUB))
Roman Rakus 2cb460
      {
Roman Rakus 2cb460
        old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
Roman Rakus 2cb460
***************
Roman Rakus 2cb460
*** 2452,2464 ****
Roman Rakus 2cb460
  	     the last process in the pipeline.  If no process exits due to a
Roman Rakus 2cb460
  	     signal, S is left as the status of the last job in the pipeline. */
Roman Rakus 2cb460
! 	  p = jobs[job]->pipe;
Roman Rakus 2cb460
! 	  do
Roman Rakus 2cb460
! 	    {
Roman Rakus 2cb460
! 	      s = p->status;
Roman Rakus 2cb460
! 	      if (WIFSIGNALED(s) || WIFSTOPPED(s))
Roman Rakus 2cb460
! 		break;
Roman Rakus 2cb460
! 	      p = p->next;
Roman Rakus 2cb460
! 	    }
Roman Rakus 2cb460
! 	  while (p != jobs[job]->pipe);
Roman Rakus 2cb460
  
Roman Rakus 2cb460
  	  if (WIFSIGNALED (s) || WIFSTOPPED (s))
Roman Rakus 2cb460
--- 2496,2500 ----
Roman Rakus 2cb460
  	     the last process in the pipeline.  If no process exits due to a
Roman Rakus 2cb460
  	     signal, S is left as the status of the last job in the pipeline. */
Roman Rakus 2cb460
! 	  s = job_signal_status (job);
Roman Rakus 2cb460
  
Roman Rakus 2cb460
  	  if (WIFSIGNALED (s) || WIFSTOPPED (s))
Roman Rakus 2cb460
***************
Roman Rakus 2cb460
*** 2494,2497 ****
Roman Rakus 2cb460
--- 2530,2551 ----
Roman Rakus 2cb460
  	    }
Roman Rakus 2cb460
  	}
Roman Rakus 2cb460
+       else if ((subshell_environment & SUBSHELL_COMSUB) && wait_sigint_received)
Roman Rakus 2cb460
+ 	{
Roman Rakus 2cb460
+ 	  /* If waiting for a job in a subshell started to do command
Roman Rakus 2cb460
+ 	     substitution, simulate getting and being killed by the SIGINT to
Roman Rakus 2cb460
+ 	     pass the status back to our parent. */
Roman Rakus 2cb460
+ 	  s = job_signal_status (job);
Roman Rakus 2cb460
+ 	
Roman Rakus 2cb460
+ 	  if (WIFSIGNALED (s) && WTERMSIG (s) == SIGINT && signal_is_trapped (SIGINT) == 0)
Roman Rakus 2cb460
+ 	    {
Roman Rakus 2cb460
+ 	      UNBLOCK_CHILD (oset);
Roman Rakus 2cb460
+ 	      restore_sigint_handler ();
Roman Rakus 2cb460
+ 	      old_sigint_handler = set_signal_handler (SIGINT, SIG_DFL);
Roman Rakus 2cb460
+ 	      if (old_sigint_handler == SIG_IGN)
Roman Rakus 2cb460
+ 		restore_sigint_handler ();
Roman Rakus 2cb460
+ 	      else
Roman Rakus 2cb460
+ 		kill (getpid (), SIGINT);
Roman Rakus 2cb460
+ 	    }
Roman Rakus 2cb460
+ 	}
Roman Rakus 2cb460
  
Roman Rakus 2cb460
        /* Moved here from set_job_status_and_cleanup, which is in the SIGCHLD
Roman Rakus 2cb460
*** ../bash-3.2/patchlevel.h	Thu Apr 13 08:31:04 2006
Roman Rakus 2cb460
--- patchlevel.h	Mon Oct 16 14:22:54 2006
Roman Rakus 2cb460
***************
Roman Rakus 2cb460
*** 26,30 ****
Roman Rakus 2cb460
     looks for to find the patch level (for the sccs version string). */
Roman Rakus 2cb460
  
Roman Rakus 2cb460
! #define PATCHLEVEL 34
Roman Rakus 2cb460
  
Roman Rakus 2cb460
  #endif /* _PATCHLEVEL_H_ */
Roman Rakus 2cb460
--- 26,30 ----
Roman Rakus 2cb460
     looks for to find the patch level (for the sccs version string). */
Roman Rakus 2cb460
  
Roman Rakus 2cb460
! #define PATCHLEVEL 35
Roman Rakus 2cb460
  
Roman Rakus 2cb460
  #endif /* _PATCHLEVEL_H_ */