signal handler function in multithreaded environment

  • Signal handlers are per-process state - that is, all the threads in a process share the same set of installed signal handler functions.
  • Signal masks are per-thread state. Signals can be blocked or unblocked on a per-thread basis.
  • Signals can be process- or thread-directed. If a signal is process-directed, then an arbitrary thread which does not currently have the signal type blocked is chosen to handle it.

A simple way to handle signals in a multi-threaded application is to create one thread as a dedicated signal-handling thread. All signals of interest are blocked in every thread; no signal handlers are established; and the signal-handling thread calls sigwaitinfo() in a loop, acting on the signals as they're received.

This means that you don't need to worry about whether the functions you want to call are async-signal-safe or not, because signals aren't handled in signal handlers - they're handled synchronously by your dedicated signal-handling thread, which can call any function it likes (for example, it can use the ordinary pthreads synchronisation functions to wake up another thread).


Be very careful: as the signal(7) page is telling, only very few functions (the "async-signal-safe" ones, see signal-safety(7) for more) can be (directly or indirectly) called inside signal handlers. Mutex related functions probably should not be called in signal handlers. See also pthreads(7)

You might consider setting a volatile sigatomic_t variable in your signal handler, and test the value of that flag from time to time. If you have C++11 (or C11) atomics, e.g. C++11 std::atomic or C11 <stdatomic.h>, you could make that volatile variable also atomic in that sense. Then use the atomic load facilities to test it.

The Qt documentation suggests the following trick: create a pipe(2) to self at startup, then have your signal handler write(2) (the write syscall is specified as being async-signal-safe) a single (or more) byte[s] to a pipe to your same process, and have your GUI event loop poll(2) the read end of that pipe.

A Linux-specific way to handle signals with Qt might be to use signalfd(2) probably with QSocketNotifier (despite the name, it works on pollable file descriptors, not only sockets). With other GUI toolkits, you probably can also add a file descriptor (the one from signalfd or pipe) to be polled.


This answer refers to POSIX threads (pthreads).

Referring 1:

Signals could be handled on thread level, yes. If more than one thread of a process handles a signal and the signal ist sent to the process, but to a specific thread it is not determined which thread's handler will handle the signal. (see man pthread_kill() for details)

Referring 2:

The signal handler will be excuted in the context of the thread which set it. This includes the main thread.

Referring 3:

If more than one signal of the same type is sent to the same process they might be condensed in into only one signal before leaving the signal queue. Whether this could be differentiate to the thread level I do not know for sure, I have to admit.

Referring 4:

If shared resources are involved in the game: yes, at least for the parts of the handlers' code accessing those resources concurrently. And moreover this also depends on the logic you try to implement.