| There is also a charming statement in POSIX standard that If the signal occurs other than as the result of calling abort(), raise(),
[CX] [Option Start] kill(), pthread_kill(), or sigqueue(), [Option End] the
behavior is undefined if the signal handler refers to any object with static
storage duration other than by assigning a value to an object declared as
volatile sig_atomic_t, or if the signal handler calls any function in the
standard library other than one of the functions listed in Signal Concepts.
You literally can't read any global/static variables and you can only write to global/static variables that are declared to be volatile sig_atomic_t. This tremendously shrinks the amount of useful work you can do with the signal-safe functions from the standard library. |
| |
| ▲ | Joker_vD a day ago | parent [-] | | No, I understand that. I just find it deeply ironic that when an interrupt/signal arrives, pretty much the only thing you can do to handle it, is to raise some flag, then leave the handler and continue doing whatever you were doing in a message loop. Like, why even bother with supporting function callbacks in sigaction() etc? Just have each thread have a chunk of volatile memory where the kernel writes info about the arrived signals, and that's it, that's your signal handling framework. In fact, here is another, a very fresh, example from POSIX: [0]. There is an example at how to use SIGWINCH signal handler with tcgetwinsize(). Just look at this thing of terrible beauty, notice that SIG_ATOMIC_MAX is not required to bigger than a byte's worth of data, and also read the whole of "APPLICATION USAGE" section. "Multi-threaded applications should avoid the signal handler idiom in general", gee, I wonder why. And of course, the signal may never be generated in the first place, so "[s]uch processes must periodically poll the current terminal window size if needed". What a solid technical foundation to build race-free, bug-free applications on top of. [0] https://pubs.opengroup.org/onlinepubs/9799919799/functions/t... | | |
| ▲ | whateverboat 18 hours ago | parent | next [-] | | > No, I understand that. I just find it deeply ironic that when an interrupt/signal arrives, pretty much the only thing you can do to handle it, is to raise some flag, then leave the handler and continue doing whatever you were doing in a message loop. That's how most hardware interrupts would also work. | | | |
| ▲ | nottorp a day ago | parent | prev | next [-] | | "From boils, mildew and dirt / I've brought forth new beauty and new worth." [1] Let's call them crippled interrupts. As long as you don't think of them as a message queue... In their defense, the original signals were there mostly for "handle this or I'll terminate you" conditions. Then stuff got bolted on... [1] Possibly LLM hallucinated translation from a Romanian poet. Although it did give me a link to a paywalled essay that I couldn't verify. | |
| ▲ | westurner 21 hours ago | parent | prev [-] | | How would you fix signals and do you propose a complete set of patterns for safe concurrency? And so why is there limited scope for signal handlers? Should you use signal handlers with eBPF? | | |
| ▲ | kstenerud 19 hours ago | parent [-] | | It's not really possible to make them safer without hurting performance. Signals break the C virtual machine guarantees (atomics, memory consistency, register consistency, etc), and the only way to re-establish them for edge cases like signals would be to cripple the rest of the program with extra checks (basically making ALL data volatile). |
|
|
|