]>
Commit | Line | Data |
---|---|---|
2eae9c88 AM |
1 | BASH PATCH REPORT |
2 | ================= | |
3 | ||
4 | Bash-Release: 3.2 | |
5 | Patch-ID: bash32-035 | |
6 | ||
7 | Bug-Reported-by: Ingo Molnar <mingo@elte.hu> | |
8 | Bug-Reference-ID: <20071205202901.GA25202@elte.hu> | |
9 | Bug-Reference-URL: http://lists.gnu.org/archive/html/bug-bash/2007-12/msg00014.html | |
10 | ||
11 | Bug-Description: | |
12 | ||
13 | Bash incorrectly puts the second and subsequent children spawned by a | |
14 | shell forked to run a command substitution in the wrong process group. | |
15 | ||
16 | Patch: | |
17 | ||
18 | *** ../bash-3.2-patched/subst.c 2007-12-13 22:31:21.000000000 -0500 | |
19 | --- subst.c 2008-01-17 22:48:15.000000000 -0500 | |
20 | *************** | |
21 | *** 4621,4627 **** | |
22 | ||
23 | #if defined (JOB_CONTROL) | |
24 | set_sigchld_handler (); | |
25 | stop_making_children (); | |
26 | ! pipeline_pgrp = old_pipeline_pgrp; | |
27 | #else | |
28 | stop_making_children (); | |
29 | --- 4721,4728 ---- | |
30 | ||
31 | #if defined (JOB_CONTROL) | |
32 | set_sigchld_handler (); | |
33 | stop_making_children (); | |
34 | ! if (pid != 0) | |
35 | ! pipeline_pgrp = old_pipeline_pgrp; | |
36 | #else | |
37 | stop_making_children (); | |
38 | *** ../bash-3.2-patched/jobs.c 2007-08-25 13:46:59.000000000 -0400 | |
39 | --- jobs.c 2007-12-08 16:47:43.000000000 -0500 | |
40 | *************** | |
41 | *** 251,254 **** | |
42 | --- 251,255 ---- | |
43 | static int set_job_status_and_cleanup __P((int)); | |
44 | ||
45 | + static WAIT job_signal_status __P((int)); | |
46 | static WAIT raw_job_exit_status __P((int)); | |
47 | ||
48 | *************** | |
49 | *** 2220,2223 **** | |
50 | --- 2238,2261 ---- | |
51 | } | |
52 | ||
53 | + static WAIT | |
54 | + job_signal_status (job) | |
55 | + int job; | |
56 | + { | |
57 | + register PROCESS *p; | |
58 | + WAIT s; | |
59 | + | |
60 | + p = jobs[job]->pipe; | |
61 | + do | |
62 | + { | |
63 | + s = p->status; | |
64 | + if (WIFSIGNALED(s) || WIFSTOPPED(s)) | |
65 | + break; | |
66 | + p = p->next; | |
67 | + } | |
68 | + while (p != jobs[job]->pipe); | |
69 | + | |
70 | + return s; | |
71 | + } | |
72 | + | |
73 | /* Return the exit status of the last process in the pipeline for job JOB. | |
74 | This is the exit status of the entire job. */ | |
75 | *************** | |
76 | *** 2302,2310 **** | |
77 | received, only if one of the jobs run is killed via SIGINT. If | |
78 | job control is not set, the job will be run in the same pgrp as | |
79 | ! the shell, and the shell will see any signals the job gets. */ | |
80 | ||
81 | /* This is possibly a race condition -- should it go in stop_pipeline? */ | |
82 | wait_sigint_received = 0; | |
83 | ! if (job_control == 0) | |
84 | { | |
85 | old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler); | |
86 | --- 2343,2354 ---- | |
87 | received, only if one of the jobs run is killed via SIGINT. If | |
88 | job control is not set, the job will be run in the same pgrp as | |
89 | ! the shell, and the shell will see any signals the job gets. In | |
90 | ! fact, we want this set every time the waiting shell and the waited- | |
91 | ! for process are in the same process group, including command | |
92 | ! substitution. */ | |
93 | ||
94 | /* This is possibly a race condition -- should it go in stop_pipeline? */ | |
95 | wait_sigint_received = 0; | |
96 | ! if (job_control == 0 || (subshell_environment&SUBSHELL_COMSUB)) | |
97 | { | |
98 | old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler); | |
99 | *************** | |
100 | *** 2452,2464 **** | |
101 | the last process in the pipeline. If no process exits due to a | |
102 | signal, S is left as the status of the last job in the pipeline. */ | |
103 | ! p = jobs[job]->pipe; | |
104 | ! do | |
105 | ! { | |
106 | ! s = p->status; | |
107 | ! if (WIFSIGNALED(s) || WIFSTOPPED(s)) | |
108 | ! break; | |
109 | ! p = p->next; | |
110 | ! } | |
111 | ! while (p != jobs[job]->pipe); | |
112 | ||
113 | if (WIFSIGNALED (s) || WIFSTOPPED (s)) | |
114 | --- 2496,2500 ---- | |
115 | the last process in the pipeline. If no process exits due to a | |
116 | signal, S is left as the status of the last job in the pipeline. */ | |
117 | ! s = job_signal_status (job); | |
118 | ||
119 | if (WIFSIGNALED (s) || WIFSTOPPED (s)) | |
120 | *************** | |
121 | *** 2494,2497 **** | |
122 | --- 2530,2551 ---- | |
123 | } | |
124 | } | |
125 | + else if ((subshell_environment & SUBSHELL_COMSUB) && wait_sigint_received) | |
126 | + { | |
127 | + /* If waiting for a job in a subshell started to do command | |
128 | + substitution, simulate getting and being killed by the SIGINT to | |
129 | + pass the status back to our parent. */ | |
130 | + s = job_signal_status (job); | |
131 | + | |
132 | + if (WIFSIGNALED (s) && WTERMSIG (s) == SIGINT && signal_is_trapped (SIGINT) == 0) | |
133 | + { | |
134 | + UNBLOCK_CHILD (oset); | |
135 | + restore_sigint_handler (); | |
136 | + old_sigint_handler = set_signal_handler (SIGINT, SIG_DFL); | |
137 | + if (old_sigint_handler == SIG_IGN) | |
138 | + restore_sigint_handler (); | |
139 | + else | |
140 | + kill (getpid (), SIGINT); | |
141 | + } | |
142 | + } | |
143 | ||
144 | /* Moved here from set_job_status_and_cleanup, which is in the SIGCHLD | |
145 | *** ../bash-3.2/patchlevel.h Thu Apr 13 08:31:04 2006 | |
146 | --- patchlevel.h Mon Oct 16 14:22:54 2006 | |
147 | *************** | |
148 | *** 26,30 **** | |
149 | looks for to find the patch level (for the sccs version string). */ | |
150 | ||
151 | ! #define PATCHLEVEL 34 | |
152 | ||
153 | #endif /* _PATCHLEVEL_H_ */ | |
154 | --- 26,30 ---- | |
155 | looks for to find the patch level (for the sccs version string). */ | |
156 | ||
157 | ! #define PATCHLEVEL 35 | |
158 | ||
159 | #endif /* _PATCHLEVEL_H_ */ |