Calling the signal()
function in a multithreaded program is undefined behavior, according to the C Standard, subclause 7.14.1.1, paragraph 7 [ISO/IEC 9899:2011].
This rule is a specific instance of SIG02-C. Avoid using signals to implement normal functionality.
Noncompliant Code Example
This noncompliant code sets a signal handler , while also setting a child thread to do work. This , which results in undefined behavior.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <signal.h> #include <threads.h> volatile sig_atomic_t flag = 0; void handler(int signum) { flag = 1; } /* Runs until user sends SIGUSR1. */ int func(void *data) { while (!flag) { /* ... */ } return 0; } int main(void) { signal(SIGUSR1, handler); /* Undefined! */ thrd_t tid; if (thrd_success != thrd_create(&tid, func, NULL)) { /* Handle Errorerror */ } /* ... */ return 0; } |
Compliant Solution
This code compliant solution dispenses with the signal handler , and uses an atomic_flag
to indicate when the child thread should terminate its loop.:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdatomic.h> #include <threads.h> atomic_flag flag = ATOMIC_VAR_INIT(0); int func(void *data) { while (!flag) { /* ... */ } return 0; } int main(void) { int result; thrd_t tid; if (thrd_success != thrd_create(&tid, func, NULL)) { /* Handle Errorerror */ } /* ... */ /* Set flag when done. */ while (!atomic_flag_test_and_set(&flag)) ; /* Continue attempts. */ return 0; } |
Exceptions
CON37-EX0EX1: Platforms that provide defined behavior when multithreaded programs use custom signal handlers are exempt from this rule. This exception would include POSIX, for example.
...
Mixing signals and threads causes undefined behavior.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
CON37-C | lowLow | probableProbable | lowLow | P6 | L2 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Bibliography
...
...