I want to print a number into log or to a terminal using write
(or any async-safe function) inside a signal handler. I would prefer not to use buffered I/O.
Is there an easy and recommended way to do that ?
For example in place of printf
, below I would prefer write
(or any asyn safe function).
void signal_handler(int sig)
{
pid_t pid;
int stat;
int old_errno = errno;
while((pid = waitpid(-1, &stat, WNOHANG)) > 0)
printf("child %d terminated\n", pid);
errno = old_errno;
return;
}
Printing strings is easy. In place of the printf
above I can use (without printing pid
):
write(STDOUT_FILENO, "child terminated", 16);
Implement your own async-signal-safe
snprintf("%d
and usewrite
It is not as bad as I thought, How to convert an int to string in C? has several implementations.
The POSIX program below counts to stdout the number of times it received SIGINT so far, which you can trigger with
Ctrl + C
.You can exit the program with
Ctrl + \
(SIGQUIT).main.c:
Compile and run:
After pressing Ctrl + C fifteen times, the terminal shows:
Here is a related program that creates a more complex format string: How to avoid using printf in a signal handler?
Tested on Ubuntu 18.04. GitHub upstream.
If you insist on using xprintf() inside a signal handler you can always roll your own version that does not rely on buffered I/O:
If you really insist on doing the printing from a signal handler, you basically have 2 options:
Block the signal except in a dedicated thread you create for handling the signal. This special thread can simply perform
for (;;) pause();
and sincepause
is async-signal-safe, the signal handler is allowed to use any functions it wants; it's not restricted to only async-signal-safe functions. On the other hand, it does have to access shared resources in a thread-safe way, since you're now dealing with threads.Write your own code for converting integers to decimal strings. It's just a simple loop of using
%10
and/10
to peel off the last digit and storing them to a short array.However, I would highly recommend getting this operation out of the signal handler, using the self-pipe trick or similar.