...
If the request to set the signal to default can be honored, the signal()
function returns the value of the signal handler for the most recent successful call to the signal()
function for the specified signal. Otherwise, a value of SIG_ERR
is returned and a positive value is stored in errno
.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <signal.h> #include <stdlib.h> #include <string.h> typedef void (*pfv)(int); void handler(int signum) { pfv old_handler = signal(signum, SIG_DFL); if (old_handler == SIG_ERR) { perror("SIGINT handler"); /* undefined behavior */ /* handle error condition */ } } int main(void) { pfv old_handler = signal(SIGINT, handler); if (old_handler == SIG_ERR) { perror("SIGINT handler"); /* handle error condition */ } /* main code loop */ return 0; } |
...
The compliant solution does not reference errno
and does not return from the signal handler if the signal()
call fails.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <signal.h> #include <stdlib.h> #include <string.h> typedef void (*pfv)(int); void handler(int signum) { pfv old_handler = signal(signum, SIG_DFL); if (old_handler == SIG_ERR) { abort(); } } int main(void) { pfv old_handler = signal(SIGINT, handler); if (old_handler == SIG_ERR) { perror("SIGINT handler"); /* handle error condition */ } /* main code loop */ return 0; } |
...
The signal handler in this noncompliant code example alters the value of errno
, and, as a result, it can cause incorrect error handling if executed in between a failed function call and the subsequent inspection of errno
.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stddef.h> #include <signal.h> #include <errno.h> #include <sys/wait.h> void reaper(int signum) { errno = 0; for (;;) { int rc = waitpid(-1, NULL, WNOHANG); if ( (0 == rc) || (-1 == rc && EINTR != errno) ) break; } if (ECHILD != errno) { /* handle error */ } } int main(void) { struct sigaction act; act.sa_handler = reaper; act.sa_flags = 0; if (sigemptyset(&act.sa_mask) != 0) { /* handle error */ } if (sigaction(SIGCHLD, &act, NULL) != 0) { /* handle error */ } /* ... */ return 0; } |
...
The compliant solution saves and restores the value of errno
in the signal handler.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stddef.h> #include <signal.h> #include <errno.h> #include <sys/wait.h> void reaper(int signum) { int save_errno = errno; errno = 0; for (;;) { int rc = waitpid(-1, NULL, WNOHANG); if ( (0 == rc) || (-1 == rc && EINTR != errno) ) break; } if (ECHILD != errno) { /* handle error */ } errno = save_errno; } int main(void) { struct sigaction act; act.sa_handler = reaper; act.sa_flags = 0; if (sigemptyset(&act.sa_mask) != 0) { /* handle error */ } if (sigaction(SIGCHLD, &act, NULL) != 0) { /* handle error */ } /* ... */ return 0; } |
...