nih_signal_handler() increments signals_caught[signum] per signal; nih_signal_poll() is responsible for checking and resetting the count.
However, a signal can arrive after nih_signal_poll() decides not to run the handler (because signals_caught[signum] is 0) but before the signals_caught counts are reset at the end of the function. (This is the classic atomicity problem when waiting for signals --- see pselect(2) for background.)
The signal pipe will have been written, which does ensure that nih_main_loop() is guaranteed to wake up again on the next round, but because signals_caught[signum] remains zero for the affected signal, that instance of the signal will be silently ignored when nih_signal_handler() is next called. This can lead to a deadlock if notification of the signal is required for the program to make progress (such as waiting for SIGCHLD to arrive).
The attached patch may serve as a workaround, but it's not been extensively tested.
I know of no real-world deadlock caused by this bug, but I spotted it when investigating a separate deadlock issue.
nih_signal_ handler( ) increments signals_ caught[ signum] per signal; nih_signal_poll() is responsible for checking and resetting the count.
However, a signal can arrive after nih_signal_poll() decides not to run the handler (because signals_ caught[ signum] is 0) but before the signals_caught counts are reset at the end of the function. (This is the classic atomicity problem when waiting for signals --- see pselect(2) for background.)
The signal pipe will have been written, which does ensure that nih_main_loop() is guaranteed to wake up again on the next round, but because signals_ caught[ signum] remains zero for the affected signal, that instance of the signal will be silently ignored when nih_signal_ handler( ) is next called. This can lead to a deadlock if notification of the signal is required for the program to make progress (such as waiting for SIGCHLD to arrive).
The attached patch may serve as a workaround, but it's not been extensively tested.
I know of no real-world deadlock caused by this bug, but I spotted it when investigating a separate deadlock issue.