bug-bash
[Top][All Lists]
Advanced

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

Re: wait skips signals but first one


From: Chet Ramey
Subject: Re: wait skips signals but first one
Date: Sat, 3 Feb 2024 15:25:30 -0500
User-agent: Mozilla Thunderbird

On 2/3/24 10:28 AM, Mykyta Dorokhin wrote:

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:

One explanation for this is SIGUSR1 being blocked when the shell is
invoked. Another is that sigsetjmp/siglongjmp are either not available
(or configure doesn't think they are) or don't properly save and restore
the signal mask.


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

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.

Bash does have an autoconf test for this, but it didn't change as part
of this push. You can check what MUST_REINSTALL_SIGHANDLERS is set to
in config.h, but I suspect it won't be different.

And `not being built correctly for Linux' would mean your Debian and my
Red Hat tests would fail.


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.

If you mean wait(2), it doesn't get restarted. waitpid(2) will return
-1/EINTR since it received a caught signal.


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

Correct, the trap signal handler doesn't assume that system calls are
restarted.

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    chet@case.edu    http://tiswww.cwru.edu/~chet/

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature


reply via email to

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