[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().
- Re[2]: wait skips signals but first one,
Mykyta Dorokhin <=