diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2020-02-18 16:46:01 +0100 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2020-02-18 16:46:01 +0100 |
| commit | 23bc562a0556d1c0ddad4252fa8d46c863b5fa88 (patch) | |
| tree | 3ad95cdddd273d569f55c57dcb6fe8f6ae488d51 /shell | |
| parent | 47eb979404735b9528538968cb5eaac7355a0c5a (diff) | |
| download | busybox-w32-23bc562a0556d1c0ddad4252fa8d46c863b5fa88.tar.gz busybox-w32-23bc562a0556d1c0ddad4252fa8d46c863b5fa88.tar.bz2 busybox-w32-23bc562a0556d1c0ddad4252fa8d46c863b5fa88.zip | |
ash,hush: add comment about masked SIGCHLD, handle SIG_IGNed SIGHUP as in bash
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/ash.c | 26 | ||||
| -rw-r--r-- | shell/hush.c | 20 |
2 files changed, 37 insertions, 9 deletions
diff --git a/shell/ash.c b/shell/ash.c index ff594050c..fea4b10a7 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
| @@ -4307,8 +4307,19 @@ wait_block_or_sig(int *status) | |||
| 4307 | #if 1 | 4307 | #if 1 |
| 4308 | sigfillset(&mask); | 4308 | sigfillset(&mask); |
| 4309 | sigprocmask2(SIG_SETMASK, &mask); /* mask is updated */ | 4309 | sigprocmask2(SIG_SETMASK, &mask); /* mask is updated */ |
| 4310 | while (!got_sigchld && !pending_sig) | 4310 | while (!got_sigchld && !pending_sig) { |
| 4311 | sigsuspend(&mask); | 4311 | sigsuspend(&mask); |
| 4312 | /* ^^^ add "sigdelset(&mask, SIGCHLD);" before sigsuspend | ||
| 4313 | * to make sure SIGCHLD is not masked off? | ||
| 4314 | * It was reported that this: | ||
| 4315 | * fn() { : | return; } | ||
| 4316 | * shopt -s lastpipe | ||
| 4317 | * fn | ||
| 4318 | * exec ash SCRIPT | ||
| 4319 | * under bash 4.4.23 runs SCRIPT with SIGCHLD masked, | ||
| 4320 | * making "wait" commands in SCRIPT block forever. | ||
| 4321 | */ | ||
| 4322 | } | ||
| 4312 | sigprocmask(SIG_SETMASK, &mask, NULL); | 4323 | sigprocmask(SIG_SETMASK, &mask, NULL); |
| 4313 | #else /* unsafe: a signal can set pending_sig after check, but before pause() */ | 4324 | #else /* unsafe: a signal can set pending_sig after check, but before pause() */ |
| 4314 | while (!got_sigchld && !pending_sig) | 4325 | while (!got_sigchld && !pending_sig) |
| @@ -14170,11 +14181,6 @@ init(void) | |||
| 14170 | sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */ | 14181 | sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */ |
| 14171 | setsignal(SIGCHLD); | 14182 | setsignal(SIGCHLD); |
| 14172 | 14183 | ||
| 14173 | /* bash re-enables SIGHUP which is SIG_IGNed on entry. | ||
| 14174 | * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$" | ||
| 14175 | */ | ||
| 14176 | signal(SIGHUP, SIG_DFL); | ||
| 14177 | |||
| 14178 | { | 14184 | { |
| 14179 | char **envp; | 14185 | char **envp; |
| 14180 | const char *p; | 14186 | const char *p; |
| @@ -14512,6 +14518,14 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
| 14512 | } | 14518 | } |
| 14513 | #endif | 14519 | #endif |
| 14514 | state4: /* XXX ??? - why isn't this before the "if" statement */ | 14520 | state4: /* XXX ??? - why isn't this before the "if" statement */ |
| 14521 | |||
| 14522 | /* Interactive bash re-enables SIGHUP which is SIG_IGNed on entry. | ||
| 14523 | * Try: | ||
| 14524 | * trap '' hup; bash; echo RET # type "kill -hup $$", see SIGHUP having effect | ||
| 14525 | * trap '' hup; bash -c 'kill -hup $$; echo ALIVE' # here SIGHUP is SIG_IGNed | ||
| 14526 | */ | ||
| 14527 | signal(SIGHUP, SIG_DFL); | ||
| 14528 | |||
| 14515 | cmdloop(1); | 14529 | cmdloop(1); |
| 14516 | } | 14530 | } |
| 14517 | #if PROFILE | 14531 | #if PROFILE |
diff --git a/shell/hush.c b/shell/hush.c index 6e44d4e11..bced388bf 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
| @@ -9775,10 +9775,14 @@ static void install_sighandlers(unsigned mask) | |||
| 9775 | */ | 9775 | */ |
| 9776 | if (sig == SIGCHLD) | 9776 | if (sig == SIGCHLD) |
| 9777 | continue; | 9777 | continue; |
| 9778 | /* bash re-enables SIGHUP which is SIG_IGNed on entry. | 9778 | /* Interactive bash re-enables SIGHUP which is SIG_IGNed on entry. |
| 9779 | * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$" | 9779 | * Try: |
| 9780 | * trap '' hup; bash; echo RET # type "kill -hup $$", see SIGHUP having effect | ||
| 9781 | * trap '' hup; bash -c 'kill -hup $$; echo ALIVE' # here SIGHUP is SIG_IGNed | ||
| 9780 | */ | 9782 | */ |
| 9781 | //if (sig == SIGHUP) continue; - TODO? | 9783 | if (sig == SIGHUP && G_interactive_fd) |
| 9784 | continue; | ||
| 9785 | /* Unless one of the above signals, is it SIG_IGN? */ | ||
| 9782 | if (old_handler == SIG_IGN) { | 9786 | if (old_handler == SIG_IGN) { |
| 9783 | /* oops... restore back to IGN, and record this fact */ | 9787 | /* oops... restore back to IGN, and record this fact */ |
| 9784 | install_sighandler(sig, old_handler); | 9788 | install_sighandler(sig, old_handler); |
| @@ -11554,6 +11558,16 @@ static int wait_for_child_or_signal(struct pipe *waitfor_pipe, pid_t waitfor_pid | |||
| 11554 | /* It is vitally important for sigsuspend that SIGCHLD has non-DFL handler! */ | 11558 | /* It is vitally important for sigsuspend that SIGCHLD has non-DFL handler! */ |
| 11555 | /* Note: sigsuspend invokes signal handler */ | 11559 | /* Note: sigsuspend invokes signal handler */ |
| 11556 | sigsuspend(&oldset); | 11560 | sigsuspend(&oldset); |
| 11561 | /* ^^^ add "sigdelset(&oldset, SIGCHLD)" before sigsuspend | ||
| 11562 | * to make sure SIGCHLD is not masked off? | ||
| 11563 | * It was reported that this: | ||
| 11564 | * fn() { : | return; } | ||
| 11565 | * shopt -s lastpipe | ||
| 11566 | * fn | ||
| 11567 | * exec hush SCRIPT | ||
| 11568 | * under bash 4.4.23 runs SCRIPT with SIGCHLD masked, | ||
| 11569 | * making "wait" commands in SCRIPT block forever. | ||
| 11570 | */ | ||
| 11557 | restore: | 11571 | restore: |
| 11558 | sigprocmask(SIG_SETMASK, &oldset, NULL); | 11572 | sigprocmask(SIG_SETMASK, &oldset, NULL); |
| 11559 | check_sig: | 11573 | check_sig: |
