Code in question first (minimized case):
#include <stdio.h>
#include <signal.h>
int counter = 0;
void react_to_signal(int n) {
    fprintf(stderr, "Caught!\n");
    counter++;
}
int main(int argc, char** argv) {
    signal(SIGINFO, react_to_signal);
    while (1) {
        printf("%d\n", counter);
    }
    return 0;
}
I run the code, it loops as it should, printing out 0. Then in another shell..
kill -s SIGINFO <pid_of_my_process>
Signal is delivered, c is incremented .. but the fprintf doesn't happen.
Why is this so? In what environment/context does handler code run? Where can I read up on this?
You can use printf in signal handlers if you are using the pthread library.
printf is non-async-signal-safe because, as you describe, it ends up manipulating global state without synchronisation. For added fun, it's not necessarily re-entrant. In your example, the signal might be handled while the first printf is running, and the second printf could mess up the state of the first call.
A signal can be generated by calling raise() or kill() system calls. raise() sends a signal to the current process, kill() sends a signal to a specific process. A signal handler is a function which is called by the target environment when the corresponding signal occurs.
The signal() system call just installs the handler: "signal() sets the disposition of the signal signum to handler, which is either SIG_IGN, SIG_DFL, or the address of a programmer-defined function (a "signal handler")." There you go.
In short: you cannot safely use printf within a signal handler.
There's a list of authorized functions in signal handler's man page. There is not fprintf in it.
That's because this function is not reentrant, mainly because it can use malloc and free.
See this post for a detailed explanation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With