POSIX could make everyone’s life easier if there was a standard facility to make signals run on dedicated “signal handling threads”. If my SIGINT handler has its own thread that only ever runs that handler (and never runs it re-enterantly), most of these safety issues go away. It is possible to implement that now, but it would be a lot easier if it were just a feature of the C library-and unlike other solutions like the self-pipe trick, the coding model is essentially unchanged (no assumption the program has an event loop). That doesn’t really work for inherently thread-specific signals such as SIGSEGV, but far fewer people are interested in handling those
That doesn't really work. For a separate thread to be able to tun the signal handler meaningfully, the thread that caused the signal must be stopped. Which would cause the same reentrancy problems.
For process-wide signals you can already have dedicated threads.
UNIX signals historically didn't make a distinction between interrupts and exceptions. Some of that distinction has crept in over time, but it's not as explicit as it should be. An exception means the currently executing thread hit a condition that stopped execution, such as a stack overflow, a memory protection violation, a divide by zero, a floating point overflow, bad system call, etc. Those have to be handled by the current thread, which isn't going anywhere until the problem is resolved. Control may be inside locks. You're going to have to abort, unwind, or repair the situation from within that thread.
Other signals indicate external events which the program ought to do something about, but don't stop current execution. Those can be handled by any thread, and often are routed to some event-handling thread.
Then there's cancellation. If you need to stop a thread, how do you do that? Some operating systems have explicit thread cancellation or inter-thread exceptions.
These are the three main cases. Trying to handle all three through one mechanism has resulted in the proliferation of Linux signal handling modes, flags, and functions.
> That doesn't really work. For a separate thread to be able to tun the signal handler meaningfully, the thread that caused the signal must be stopped.
As I said, I'm not talking about thread-specific signals (exceptions) such as SIGSEGV, just process-level signals such as SIGINT. pthread_mutex_lock() isn't async-signal-safe, so you can't reliably use it from a signal handler, since it can cause undefined behaviour if a thread is in the middle of operating on a mutex, and then gets a signal which tries to operate on the same mutex. Whereas, if the signal handler is on a separate thread, it can use thread-safe-but-not-async-signal-safe APIs such as pthread_mutex_lock(), and it doesn't have to stop any other thread to safely do so
> For process-wide signals you can already have dedicated threads.
You can but it is work to set them up. People would be more likely to do it if there was a simple API, e.g. thread_signal(), which would be like signal() but creates a signal handling thread for given signal and handler, and blocks that signal on all the other threads in the process. Or maybe for sigaction() an SA_OWNTHREAD flag which gives the signal handler its own thread.