ash,hush: add comment about masked SIGCHLD, handle SIG_IGNed SIGHUP as in bash

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2020-02-18 16:46:01 +01:00
parent 47eb979404
commit 23bc562a05
2 changed files with 37 additions and 9 deletions

View File

@ -4307,8 +4307,19 @@ wait_block_or_sig(int *status)
#if 1 #if 1
sigfillset(&mask); sigfillset(&mask);
sigprocmask2(SIG_SETMASK, &mask); /* mask is updated */ sigprocmask2(SIG_SETMASK, &mask); /* mask is updated */
while (!got_sigchld && !pending_sig) while (!got_sigchld && !pending_sig) {
sigsuspend(&mask); sigsuspend(&mask);
/* ^^^ add "sigdelset(&mask, SIGCHLD);" before sigsuspend
* to make sure SIGCHLD is not masked off?
* It was reported that this:
* fn() { : | return; }
* shopt -s lastpipe
* fn
* exec ash SCRIPT
* under bash 4.4.23 runs SCRIPT with SIGCHLD masked,
* making "wait" commands in SCRIPT block forever.
*/
}
sigprocmask(SIG_SETMASK, &mask, NULL); sigprocmask(SIG_SETMASK, &mask, NULL);
#else /* unsafe: a signal can set pending_sig after check, but before pause() */ #else /* unsafe: a signal can set pending_sig after check, but before pause() */
while (!got_sigchld && !pending_sig) while (!got_sigchld && !pending_sig)
@ -14170,11 +14181,6 @@ init(void)
sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */ sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
setsignal(SIGCHLD); setsignal(SIGCHLD);
/* bash re-enables SIGHUP which is SIG_IGNed on entry.
* Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
*/
signal(SIGHUP, SIG_DFL);
{ {
char **envp; char **envp;
const char *p; const char *p;
@ -14512,6 +14518,14 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
} }
#endif #endif
state4: /* XXX ??? - why isn't this before the "if" statement */ state4: /* XXX ??? - why isn't this before the "if" statement */
/* Interactive bash re-enables SIGHUP which is SIG_IGNed on entry.
* Try:
* trap '' hup; bash; echo RET # type "kill -hup $$", see SIGHUP having effect
* trap '' hup; bash -c 'kill -hup $$; echo ALIVE' # here SIGHUP is SIG_IGNed
*/
signal(SIGHUP, SIG_DFL);
cmdloop(1); cmdloop(1);
} }
#if PROFILE #if PROFILE

View File

@ -9775,10 +9775,14 @@ static void install_sighandlers(unsigned mask)
*/ */
if (sig == SIGCHLD) if (sig == SIGCHLD)
continue; continue;
/* bash re-enables SIGHUP which is SIG_IGNed on entry. /* Interactive bash re-enables SIGHUP which is SIG_IGNed on entry.
* Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$" * Try:
* trap '' hup; bash; echo RET # type "kill -hup $$", see SIGHUP having effect
* trap '' hup; bash -c 'kill -hup $$; echo ALIVE' # here SIGHUP is SIG_IGNed
*/ */
//if (sig == SIGHUP) continue; - TODO? if (sig == SIGHUP && G_interactive_fd)
continue;
/* Unless one of the above signals, is it SIG_IGN? */
if (old_handler == SIG_IGN) { if (old_handler == SIG_IGN) {
/* oops... restore back to IGN, and record this fact */ /* oops... restore back to IGN, and record this fact */
install_sighandler(sig, old_handler); install_sighandler(sig, old_handler);
@ -11554,6 +11558,16 @@ static int wait_for_child_or_signal(struct pipe *waitfor_pipe, pid_t waitfor_pid
/* It is vitally important for sigsuspend that SIGCHLD has non-DFL handler! */ /* It is vitally important for sigsuspend that SIGCHLD has non-DFL handler! */
/* Note: sigsuspend invokes signal handler */ /* Note: sigsuspend invokes signal handler */
sigsuspend(&oldset); sigsuspend(&oldset);
/* ^^^ add "sigdelset(&oldset, SIGCHLD)" before sigsuspend
* to make sure SIGCHLD is not masked off?
* It was reported that this:
* fn() { : | return; }
* shopt -s lastpipe
* fn
* exec hush SCRIPT
* under bash 4.4.23 runs SCRIPT with SIGCHLD masked,
* making "wait" commands in SCRIPT block forever.
*/
restore: restore:
sigprocmask(SIG_SETMASK, &oldset, NULL); sigprocmask(SIG_SETMASK, &oldset, NULL);
check_sig: check_sig: