bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re[2]: wait skips signals but first one


From: Mykyta Dorokhin
Subject: Re[2]: wait skips signals but first one
Date: Sat, 03 Feb 2024 17:28:58 +0200

Hello again,


Here is another analysis that my collegue made on the issue:



Bash Compiled for wrong OS?

Analysis with strace.

After receiving SIGUSR1, Debian only blocks SIGCHLD, then clears the block:

205295 --- SIGUSR1 {si_signo=SIGUSR1, si_code=SI_USER, si_pid=205327, 
si_uid=1040} ---
205295 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
205295 rt_sigaction(SIGINT, {sa_handler=SIG_DFL, sa_mask=[], 
sa_flags=SA_RESTORER, sa_restorer=0x7f063bdb5fd0}, {sa_handler=0x5637247940b0, 
sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f063bdb5fd0}, 8) = 0
205295 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
205295 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0  # unblocks all signalas


The above is the correct action.

On our device, it blocks SIGUSR1 as well as SIGCHLD and keeps doing it over and 
over again:

6707  --- SIGUSR1 {si_signo=SIGUSR1, si_code=SI_USER, si_pid=6724, si_uid=0} ---
6707  rt_sigprocmask(SIG_BLOCK, [CHLD], [USR1 CHLD], 8) = 0
6707  rt_sigprocmask(SIG_SETMASK, [USR1 CHLD], NULL, 8) = 0
6707  rt_sigprocmask(SIG_BLOCK, NULL, [USR1 CHLD], 8) = 0
6707  write(1, ">>> TRAPPED USR1 <<<\n", 21) = 21
6707  rt_sigprocmask(SIG_BLOCK, [CHLD], [USR1 CHLD], 8) = 0
6707  rt_sigprocmask(SIG_SETMASK, [USR1 CHLD], NULL, 8) = 0
6707  rt_sigprocmask(SIG_BLOCK, [CHLD], [USR1 CHLD], 8) = 0
6707  rt_sigprocmask(SIG_SETMASK, [USR1 CHLD], NULL, 8) = 0
6707  write(1, "Iteration\n", 10)       = 10
6707  rt_sigprocmask(SIG_BLOCK, NULL, [USR1 CHLD], 8) = 0
6707  rt_sigprocmask(SIG_BLOCK, [INT TERM CHLD], [USR1 CHLD], 8) = 0
6707  clone(child_stack=NULL, 
flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x76fe9028) 
= 6725
6707  rt_sigprocmask(SIG_SETMASK, [USR1 CHLD], NULL, 8) = 0
6707  rt_sigprocmask(SIG_BLOCK, [CHLD], [USR1 CHLD], 8) = 0
6707  rt_sigprocmask(SIG_BLOCK, [CHLD], [USR1 CHLD], 8) = 0
6707  rt_sigprocmask(SIG_SETMASK, [USR1 CHLD], NULL, 8) = 0
6707  rt_sigprocmask(SIG_BLOCK, [CHLD], [USR1 CHLD], 8) = 0
6707  rt_sigprocmask(SIG_SETMASK, [USR1 CHLD], NULL, 8) = 0
6707  rt_sigprocmask(SIG_BLOCK, [CHLD], [USR1 CHLD], 8) = 0
6707  rt_sigprocmask(SIG_SETMASK, [USR1 CHLD], NULL, 8) = 0
6707  rt_sigprocmask(SIG_SETMASK, [USR1 CHLD], NULL, 8) = 0
6707  rt_sigprocmask(SIG_BLOCK, [CHLD], [USR1 CHLD], 8) = 0
6707  rt_sigprocmask(SIG_SETMASK, [USR1 CHLD], NULL, 8) = 0
6707  rt_sigprocmask(SIG_BLOCK, [CHLD], [USR1 CHLD], 8) = 0
6707  rt_sigaction(SIGINT, {sa_handler=0x46e15, sa_mask=[], 
sa_flags=SA_RESTORER, sa_restorer=0x76e90711},  <unfinished ...>
6707  <... rt_sigaction resumed>{sa_handler=0x46e15, sa_mask=[], 
sa_flags=SA_RESTORER, sa_restorer=0x76e90711}, 8) = 0
6707  wait4(-1,  <unfinished ...>

On modern systems, the OS blocks the signal that is caught during signal 
handling, and unblocks so that signal handlers are not called recursively.  The 
exception to this is if SA_NODEFER is set. On some very old UNIX systems you 
had to block the signal yourself, and there was a small window where things 
could go wrong. I suspect BASH probably has a build option to allow blocking 
signals in handlers for compatibility with other systems, and is not being 
built correctly for Linux. I suspect on those very old systems the signal was 
automatically unblocked on return, but is not done here, because the POSIX 
sigprocmask is called, which requires calling it again to unblock the signal in 
Linux.  And since wait is restarted, it never is unblocked.

According to strace no additional user flags are set when the BASH signal 
handler is put in place for SIGUSR1.

We need to look at bash build options, and possible the signal handling code, 
and sigprocmask or whatever C API they are using to call sigprocmask().


reply via email to

[Prev in Thread] Current Thread [Next in Thread]