Accessing or modifying shared objects in signal handlers can result in race conditions that can leave data in an inconsistent state. The exception to this rule is the ability to read and write to lock-free atomic objects or variables of volatile sig_atomic_t
. The need for the volatile
keyword is described in DCL34 DCL22-C. Use volatile for data that cannot be cached. It is important to note that the behavior of a program that accesses an object of any other type from a signal handler is undefined. (See undefined behavior 131 in Appendix J of the C Standard.)
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <signal.h> #include <stdlib.h> #include <string.h> char *err_msg; enum { MAX_MSG_SIZE = 24 }; void handler(int signum) { strcpy(err_msg, "SIGINT encountered."); } int main(void) { signal(SIGINT, handler); err_msg = (char *)malloc(MAX_MSG_SIZE); if (err_msg == NULL) { /* Handle error condition. */ } strcpy(err_msg, "No errors yet."); /* Main code loop. */ return 0; } |
Compliant Solution
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <signal.h> #include <stdlib.h> #include <string.h> enum { MAX_MSG_SIZE = 24 }; volatile sig_atomic_t e_flag = 0; void handler(int signum) { e_flag = 1; } int main(void) { char *err_msg = (char *)malloc(MAX_MSG_SIZE); if (err_msg == NULL) { /* Handle error condition. */ } signal(SIGINT, handler); strcpy(err_msg, "No errors yet."); /* Main code loop. */ if (e_flag) { strcpy(err_msg, "SIGINT received."); } return 0; } |
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <signal.h> extern double compute_value(); static volatile double value; /* bug: not declared sig_atomic_t */ void sigfpe_handler(int signum) { if (0.0 == value) /* bug: accessing non-sig_atomic_t object */{ value = 1.0; /* bug: SIGFPE handler returns */} } int main(void) { signal(SIGFPE, sigfpe_handler); value = compute_value(); return 0; } |
...
CERT C++ Secure Coding Standard | SIG31-CPP. Do not access shared objects in signal handlers |
ISO/IEC TS 17961 (Draft) | Accessing shared objects in signal handlers [accsig] |
MITRE CWE | CWE-662, Insufficient synchronization |
Bibliography
...
[ISO/IEC 2003] | "Signals and Interrupts" |
[Open Group 2004] | longjmp |
[OpenBSD] | signal() Man Page |
[Zalewski 2001] | "Delivering Signals for Fun and Profit" |
...