I've been trying to understand the intricacies of how POSIX threads and POSIX signals interact. In particular, I'm interested in:
For reference about why I want this, I'm researching how to convert the TclX package to support threads, or to split it up and at least make some useful parts support threads. Signals are one of those parts that is of particular interest.
- 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.)