i am trying to understand how signals works. When i put sigsuspend outside of the while loop the code works otherwise it doesn't. Why?
static void signal_handler(int sig) {
printf("SIGUSR1 has been received!");
}
int main() {
struct sigaction sigact;
sigset_t sigset;
sigemptyset(&sigset);
sigact.sa_handler = signal_handler;
sigact.sa_mask = sigset;
sigact.sa_flags = 0;
sigaction(SIGUSR1, &sigact, NULL);
while(1) {
sigsuspend(&sigset);
printf("The signal has been received!");
}
}
CodePudding user response:
When i put sigsuspend outside of the while loop the code works otherwise it doesn't.
I take you to mean that you don't see any output when you send a SIGUSR1 to a program built from the code presented. That has nothing directly to do with the looping or signaling. The problem is that the standard output is buffered by default -- line buffered when it is connected to a terminal, and otherwise fully buffered. If you send enough SIGUSR1s to the process, it will eventually print enough output to fill the buffer, and then you will see all the messages.
To see the messages immediately, either
(if stdout is connected to a terminal) add a newline to the end of each message:
printf("The signal has been received!\n");
OR
flush stdout after each
printf
:printf("The signal has been received!"); fflush(stdout);
OR
direct the output to stderr instead, which is unbuffered by default:
fprintf(stderr, "The signal has been received!");
OR even
change stdout's buffering mode:
setvbuf(stdout, NULL, _IONBF, 0);
(once is sufficient).
As for why you think you see different behavior when you call sigsuspend()
only once instead of in an infinite loop, that is because the program's open streams are automatically flushed and closed when the program terminates normally.
Additionally, printf()
is not async-signal-safe, therefore you elicit undefined behavior by calling it from a signal handler. Don't do that, even if it seems to work for you under some circumstances.