diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-05-18 15:49:07 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-05-18 15:49:07 +0200 |
| commit | 238bf187ba5708bc04065b761ffc98c877043fe4 (patch) | |
| tree | 5e149a732ecb715a0d36dbaf56f21501b8738f0e /shell | |
| parent | 51b4a9e2f192c03039f339401026752f6340df25 (diff) | |
| download | busybox-w32-238bf187ba5708bc04065b761ffc98c877043fe4.tar.gz busybox-w32-238bf187ba5708bc04065b761ffc98c877043fe4.tar.bz2 busybox-w32-238bf187ba5708bc04065b761ffc98c877043fe4.zip | |
ash: fix bug which causes signal6.tests to fail
function old new delta
trapcmd 271 277 +6
localcmd 277 275 -2
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/ash.c | 22 | ||||
| -rwxr-xr-x | shell/ash_test/ash-signals/signal6.tests | 1 |
2 files changed, 15 insertions, 8 deletions
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 | */ |
| 3273 | static void | 3275 | static void |
| 3274 | onsig(int signo) | 3276 | signal_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 |
| 3 | echo Done: $? | 2 | echo Done: $? |
