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 | |
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>
-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: |