1. For signal handling: if your signal handler needs to do more that setting a global value that ought to be read regularly by your program, consider that it might not be the mechanism you need, or that you're trying to hack around code design that have implications you really might not want to deal with.
2. For signal sending for process group control: read carefully manuals and forum helps to understand semantic subtleties between groups and sessions, as sending signals from a terminal with ctrl-<d,c,z,…> does not do the same thing than signaling processes from a program system call, which can really sway intuitions you might have on the subject.
You can do surprising stuff in signal handlers; a program I used to work on had an interrupt menu in the signal handler. You could ctrl-c it and choose various "stop", "checkpoint", "dump status info" options. Similar to https://news.ycombinator.com/item?id=37899269 although without going quite so far as to adjust the stack with longjmp(). Whether you're "allowed" to do any of these things is another matter and they're almost certainly undefined behavior.
The interaction between threads and signals is really dire though. You need to mess around with signal masking. I think we'd ended up with an architecture where one thread caught the SIGINT and passed a SIGRT to a different thread; this behaved better in some way I cannot now remember.
If you want your program to be portable to Windows and MacOS as well, prepare for things to be differently broken there.
If your program has an async loop (select or poll etc.) then you need to know about the self-pipe trick for avoiding problems with signals. https://cr.yp.to/docs/selfpipe.html
This pattern of the signal handler merely setting a global var seems robust. Of course, now the programmer must decide when and where to check the global value.
It must also be of an atomic type. POSIX specifies exactly one, namely “volatile sig_atomic_t”. I guess in C++11 etc. you can also use the language-provided atomics.
1. For signal handling: if your signal handler needs to do more that setting a global value that ought to be read regularly by your program, consider that it might not be the mechanism you need, or that you're trying to hack around code design that have implications you really might not want to deal with.
2. For signal sending for process group control: read carefully manuals and forum helps to understand semantic subtleties between groups and sessions, as sending signals from a terminal with ctrl-<d,c,z,…> does not do the same thing than signaling processes from a program system call, which can really sway intuitions you might have on the subject.
(edit: fixed wrong example with ctrl-<…> signals)