- What's the best way to control which thread
a signal is delivered to?
As @zoli2k indicated, explicitly nominating a single thread to handle all signals you want handled (or a set of threads each with specific signal responsibilities), is a good technique.
- What is the best way to tell another thread (that might actually be busy)
that the signal has arrived?[...]
- How can I safely handle passing the information that a signal has occurred
to other threads? Does this need to happen in the signal handler?
I won't say "best," but here's my recommendation:
Block all desired signals in main
, so that all threads are inherit that signal mask. Then, fashion the special signal receiving thread as a signal-driven event loop, dispatching newly arrived signals as some other intra-thread communication.
The simplest way to do this is to have the thread accept signals in a loop using sigwaitinfo
or sigtimedwait
. The thread then converts the signals somehow, perhaps broadcasting a pthread_cond_t
, waking up other threads with more I/O, enqueuing a command in an application-specific thread-safe queue, whatever.
Alternatively, the special thread could allow signals to be delivered to a signal handler, unmasking for delivery only when ready to handle signals. (Signal delivery via handlers tends to be more error-prone than signal acceptance via the sigwait
family, however.) In this case, the receiver's signal handler performs some simple and async-signal-safe action: setting sig_atomic_t
flags, calling sigaddset(&signals_i_have_seen_recently, latest_sig)
, write
() a byte to a non-blocking self-pipe, etc. Then, back in its masked main loop, the thread communicates receipt of the signal to other threads as above.
(UPDATED @caf rightly points out that sigwait
approaches are superior.)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…