aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/route.c2
-rw-r--r--shell/ash.c22
-rwxr-xr-xshell/ash_test/ash-signals/signal6.tests1
3 files changed, 16 insertions, 9 deletions
diff --git a/networking/route.c b/networking/route.c
index 241be8e09..a3199621a 100644
--- a/networking/route.c
+++ b/networking/route.c
@@ -178,7 +178,7 @@ static NOINLINE void INET_setroute(int action, char **args)
178 int prefix_len; 178 int prefix_len;
179 179
180 prefix_len = xatoul_range(prefix+1, 0, 32); 180 prefix_len = xatoul_range(prefix+1, 0, 32);
181 mask_in_addr(rt) = htonl( ~ (0xffffffffUL >> prefix_len)); 181 mask_in_addr(rt) = htonl( ~(0xffffffffUL >> prefix_len));
182 *prefix = '\0'; 182 *prefix = '\0';
183#if HAVE_NEW_ADDRT 183#if HAVE_NEW_ADDRT
184 rt.rt_genmask.sa_family = AF_INET; 184 rt.rt_genmask.sa_family = AF_INET;
diff --git a/shell/ash.c b/shell/ash.c
index 641a14035..4f2fa756b 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -208,6 +208,7 @@ struct globals_misc {
208 208
209 /* indicates specified signal received */ 209 /* indicates specified signal received */
210 uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */ 210 uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
211 uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
211 char *trap[NSIG]; 212 char *trap[NSIG];
212 char **trap_ptr; /* used only by "trap hack" */ 213 char **trap_ptr; /* used only by "trap hack" */
213 214
@@ -236,6 +237,7 @@ extern struct globals_misc *const ash_ptr_to_globals_misc;
236#define optlist (G_misc.optlist ) 237#define optlist (G_misc.optlist )
237#define sigmode (G_misc.sigmode ) 238#define sigmode (G_misc.sigmode )
238#define gotsig (G_misc.gotsig ) 239#define gotsig (G_misc.gotsig )
240#define may_have_traps (G_misc.may_have_traps )
239#define trap (G_misc.trap ) 241#define trap (G_misc.trap )
240#define trap_ptr (G_misc.trap_ptr ) 242#define trap_ptr (G_misc.trap_ptr )
241#define random_gen (G_misc.random_gen ) 243#define random_gen (G_misc.random_gen )
@@ -333,7 +335,7 @@ raise_interrupt(void)
333 /* Signal is not automatically unmasked after it is raised, 335 /* Signal is not automatically unmasked after it is raised,
334 * do it ourself - unmask all signals */ 336 * do it ourself - unmask all signals */
335 sigprocmask_allsigs(SIG_UNBLOCK); 337 sigprocmask_allsigs(SIG_UNBLOCK);
336 /* pending_sig = 0; - now done in onsig() */ 338 /* pending_sig = 0; - now done in signal_handler() */
337 339
338 ex_type = EXSIG; 340 ex_type = EXSIG;
339 if (gotsig[SIGINT - 1] && !trap[SIGINT]) { 341 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
@@ -3268,10 +3270,10 @@ ignoresig(int signo)
3268} 3270}
3269 3271
3270/* 3272/*
3271 * Signal handler. Only one usage site - in setsignal() 3273 * Only one usage site - in setsignal()
3272 */ 3274 */
3273static void 3275static void
3274onsig(int signo) 3276signal_handler(int signo)
3275{ 3277{
3276 gotsig[signo - 1] = 1; 3278 gotsig[signo - 1] = 1;
3277 3279
@@ -3366,7 +3368,7 @@ setsignal(int signo)
3366 act.sa_handler = SIG_DFL; 3368 act.sa_handler = SIG_DFL;
3367 switch (new_act) { 3369 switch (new_act) {
3368 case S_CATCH: 3370 case S_CATCH:
3369 act.sa_handler = onsig; 3371 act.sa_handler = signal_handler;
3370 act.sa_flags = 0; /* matters only if !DFL and !IGN */ 3372 act.sa_flags = 0; /* matters only if !DFL and !IGN */
3371 sigfillset(&act.sa_mask); /* ditto */ 3373 sigfillset(&act.sa_mask); /* ditto */
3372 break; 3374 break;
@@ -8443,15 +8445,16 @@ evalsubshell(union node *n, int flags)
8443 int status; 8445 int status;
8444 8446
8445 expredir(n->nredir.redirect); 8447 expredir(n->nredir.redirect);
8446 if (!backgnd && flags & EV_EXIT && !trap[0]) 8448 if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
8447 goto nofork; 8449 goto nofork;
8448 INT_OFF; 8450 INT_OFF;
8449 jp = makejob(/*n,*/ 1); 8451 jp = makejob(/*n,*/ 1);
8450 if (forkshell(jp, n, backgnd) == 0) { 8452 if (forkshell(jp, n, backgnd) == 0) {
8453 /* child */
8451 INT_ON; 8454 INT_ON;
8452 flags |= EV_EXIT; 8455 flags |= EV_EXIT;
8453 if (backgnd) 8456 if (backgnd)
8454 flags &=~ EV_TESTED; 8457 flags &= ~EV_TESTED;
8455 nofork: 8458 nofork:
8456 redirect(n->nredir.redirect, 0); 8459 redirect(n->nredir.redirect, 0);
8457 evaltreenr(n->nredir.n, flags); 8460 evaltreenr(n->nredir.n, flags);
@@ -9193,16 +9196,19 @@ evalcommand(union node *cmd, int flags)
9193 } 9196 }
9194#endif 9197#endif
9195 /* Fork off a child process if necessary. */ 9198 /* Fork off a child process if necessary. */
9196 if (!(flags & EV_EXIT) || trap[0]) { 9199 if (!(flags & EV_EXIT) || may_have_traps) {
9197 INT_OFF; 9200 INT_OFF;
9198 jp = makejob(/*cmd,*/ 1); 9201 jp = makejob(/*cmd,*/ 1);
9199 if (forkshell(jp, cmd, FORK_FG) != 0) { 9202 if (forkshell(jp, cmd, FORK_FG) != 0) {
9203 /* parent */
9200 exitstatus = waitforjob(jp); 9204 exitstatus = waitforjob(jp);
9201 INT_ON; 9205 INT_ON;
9202 TRACE(("forked child exited with %d\n", exitstatus)); 9206 TRACE(("forked child exited with %d\n", exitstatus));
9203 break; 9207 break;
9204 } 9208 }
9209 /* child */
9205 FORCE_INT_ON; 9210 FORCE_INT_ON;
9211 /* fall through to exec'ing exeternal program */
9206 } 9212 }
9207 listsetvar(varlist.list, VEXPORT|VSTACK); 9213 listsetvar(varlist.list, VEXPORT|VSTACK);
9208 shellexec(argv, path, cmdentry.u.index); 9214 shellexec(argv, path, cmdentry.u.index);
@@ -12349,6 +12355,8 @@ trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12349 action = ckstrdup(action); 12355 action = ckstrdup(action);
12350 } 12356 }
12351 free(trap[signo]); 12357 free(trap[signo]);
12358 if (action)
12359 may_have_traps = 1;
12352 trap[signo] = action; 12360 trap[signo] = action;
12353 if (signo != 0) 12361 if (signo != 0)
12354 setsignal(signo); 12362 setsignal(signo);
diff --git a/shell/ash_test/ash-signals/signal6.tests b/shell/ash_test/ash-signals/signal6.tests
index ffeded2a5..3ce151060 100755
--- a/shell/ash_test/ash-signals/signal6.tests
+++ b/shell/ash_test/ash-signals/signal6.tests
@@ -1,3 +1,2 @@
1# Bug: TERM does not trigger in the child
2{ trap "echo got TERM" TERM; sleep 3; }& sleep 1; kill $!; wait 1{ trap "echo got TERM" TERM; sleep 3; }& sleep 1; kill $!; wait
3echo Done: $? 2echo Done: $?