summaryrefslogtreecommitdiff
blob: 2e9286f34d405f525aeba87ec46c652b53f35478 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
http://bugs.gentoo.org/231775
http://lists.gnu.org/archive/html/bug-bash/2008-07/msg00010.html

A parent bash shell sometimes will set the session leader tty (using tcsetpgrp)
back to itself, taking control away from a child bash shell, due to a race
condition.  A result is that the child can then not then execute some commands
(like stty) from its init script (e.g. .bashrc).  The result I (and others)
have seen is that the bash shell will hang while reading the init script.

*** a/jobs.c
--- b/jobs.c
***************
*** 266,269 ****
--- 266,270 ----
  static void set_job_running __P((int));
  static void setjstatus __P((int));
+ static int maybe_give_terminal_to __P((pid_t, pid_t, int));
  static void mark_all_jobs_as_dead __P((void));
  static void mark_dead_jobs_as_notified __P((int));
***************
*** 637,641 ****
  	   */
  	  if (job_control && newjob->pgrp && (subshell_environment&SUBSHELL_ASYNC) == 0)
! 	    give_terminal_to (newjob->pgrp, 0);
  	}
      }
--- 638,642 ----
  	   */
  	  if (job_control && newjob->pgrp && (subshell_environment&SUBSHELL_ASYNC) == 0)
! 	    maybe_give_terminal_to (shell_pgrp, newjob->pgrp, 0);
  	}
      }
***************
*** 3833,3836 ****
--- 3834,3863 ----
  }
  
+ /* Give terminal to NPGRP iff it's currently owned by OPGRP.  FLAGS are the
+    flags to pass to give_terminal_to(). */
+ static int
+ maybe_give_terminal_to (opgrp, npgrp, flags)
+      pid_t opgrp, npgrp;
+      int flags;
+ {
+   int tpgrp;
+ 
+   tpgrp = tcgetpgrp (shell_tty);
+   if (tpgrp == npgrp)
+     {
+       terminal_pgrp = npgrp;
+       return 0;
+     }
+   else if (tpgrp != opgrp)
+     {
+ #if defined (DEBUG)
+       internal_warning ("maybe_give_terminal_to: terminal pgrp == %d shell pgrp = %d", tpgrp, opgrp);
+ #endif
+       return -1;
+     }
+   else
+     return (give_terminal_to (npgrp, flags));     
+ }
+ 
  /* Clear out any jobs in the job array.  This is intended to be used by
     children of the shell, who should not have any job structures as baggage