To a large extent - no - working with shared data in a signal handler almost always leads to a world of pain regarding flows, and also you have a mess.
By default, the signal is blocked during the operation of the signal handler (at least on linux, which may not be universal), so at least the signal handler will not be unloaded by itself. Although, if you have several threads and the signal is not blocked in other threads, the signal handler can be successfully launched simultaneously in several threads.
One thread will receive a signal and execute a handler, it will be more or less random which thread will be, although you can control it by blocking the signal in all threads that you do not want to process.
However, any of the other string of threads that processes the signal can work in parallel. The signal processing stream can start the signal processor almost anywhere in the program (until the signal is blocked). Thus, to protect this data, you need some kind of lock. The problem is that you cannot use any ordinary primitives to block threads; they are not safe for asynchronous signals. Value if you, for example. try to capture pthread_mutex_t in the signal handler, you will easily forget your program.
The only functions that you can safely call in the signal handler are those listed here . Regarding the protection of shared data, you can use sigblock () / sigunblock () as a kind of protection, ensuring that the signal handler does not start while accessing this shared data - and the signal must be blocked in all threads, otherwise it will only run in one of the streams that does not block it - descent along this road - madness.
To a large extent, the only available data that you can safely access in the signal handler is the sig_atomic_t type, in practice other types of primitive types are also safe.
What you really have to do in the signal handler is just
- set global flag
- check the box elsewhere when it fits, and do the action
or
- has some kind of main loop that tracks file descriptors for events using select () / poll () or similar.
- create a channel and control that in your main loop
- write () bytes to the channel in the signal handler
- run your code to process the signal, including protecting any shared data when mainloop detects an event on this channel
or
- Keep a spare thread around
- block this signal in all your threads
- have this spare stream loop when calling sigsuspend () with a signal mask that delivers this signal.
- run your code, including protecting any common signal processing data when sigsuspend () returns
source share