Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Printf is not working in C signal handler

Tags:

c

signals

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?

like image 913
ntl0ve Avatar asked Mar 03 '12 17:03

ntl0ve


People also ask

Can you use printf in signal handler?

You can use printf in signal handlers if you are using the pthread library.

Why is printf not a safe signal?

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.

How do signal handlers work in C?

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.

Does signal () call the signal handler?

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.


1 Answers

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.

like image 119
Coren Avatar answered Sep 17 '22 17:09

Coren