Since printf
is not reentrant, it's not supposed to be safe to use it in a signal handler. But I've seen lots of example codes that uses printf
this way.
So my question is: when do we need to avoid using printf
in a signal handler, and is there a recommended replacement?
You can use some flag variable, set that flag inside signal handler, and based on that flag call printf()
function in main() or other part of program during normal operation.
It is not safe to call all functions, such as
printf
, from within a signal handler. A useful technique is to use a signal handler to set aflag
and then check thatflag
from the main program and print a message if required.
Notice in example below, signal handler ding() set a flag alarm_fired
to 1 as SIGALRM caught and in main function alarm_fired
value is examined to conditionally call printf correctly.
static int alarm_fired = 0;
void ding(int sig) // can be called asynchronously
{
alarm_fired = 1; // set flag
}
int main()
{
pid_t pid;
printf("alarm application starting\n");
pid = fork();
switch(pid) {
case -1:
/* Failure */
perror("fork failed");
exit(1);
case 0:
/* child */
sleep(5);
kill(getppid(), SIGALRM);
exit(0);
}
/* if we get here we are the parent process */
printf("waiting for alarm to go off\n");
(void) signal(SIGALRM, ding);
pause();
if (alarm_fired) // check flag to call printf
printf("Ding!\n");
printf("done\n");
exit(0);
}
Reference: Beginning Linux Programming, 4th Edition, In this book exactly your code is explained (what you want), Chapter 11: Processes and Signals, page 484
Additionally, you need to take special care in writing handler functions because they can be called asynchronously. That is, a handler might be called at any point in the program, unpredictably. If two signals arrive during a very short interval, one handler can run within another. And It is considered better practice to declare volatile sigatomic_t
, this type are always accessed atomically, avoid uncertainty about interrupting access to a variable. (read: Atomic Data Access and Signal Handling for detail expiation).
Read Defining Signal Handlers :to learn how to write a signal handler function that can be established with the signal()
or sigaction()
functions.
List of authorized functions in manual page, calling this function inside signal handler is safe.