I need to handle Unix signals in a single-threaded application with the following goals:
- Signals doesn't mask on receive (thus, the signal handler must be reentrant).
- I am not allowed to lose signal data (thus, if a new signal comes before the handler of the previous returned, it also must be handled correctly).
I have the common multi-threaded primitives (spinlocks, semaphores, etc). But they doesn't seem enough, because my higher-level data structures (even a such simple as a list) aren't thread-safe.
My initial idea was the following:
- I use a list, in which I store the data of the incoming signal fast,
- and process them (call the possibily much slower running handlers) later, out of the critical section.
The main problem with that, that the list data structure isn't thread safe. If I lock it, I can't store a second signal anywhere. I can't wait until the previous handler exits, because on the second signal it is essentially suspended in a critical section.
Simply I don't have any idea, how to handle the following scenario:
- signal1 comes, the process suspends, and the handler of signal1 starts
- signal2 comes, the handler of signal1 suspends, and the handler of signal2 starts
- Handler of signal2 returns, execution returns to the handler signal1
- Handler of signal1 returns, execution returns to the main program.
After thinking a lot on it, I have an impression, maybe my problem is unsolvable. Am I right? How do operating systems handle similar problems (for example, possibily bursting interrupts from hardware)?