Calling the signal() function in a multithreaded program is undefined behavior. (see See undefined behavior 135.).
Noncompliant Code Example
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <signal.h>
#include <stddef.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 behavior */
thrd_t tid;
if (thrd_success != thrd_create(&tid, func, NULL)) {
/* Handle error */
}
/* ... */
return 0;
} |
NOTE: The SIGUSR1 signal value is not defined in the C Standard; consequently, this is not a C-compliant code example.
...
This compliant solution uses an object of type atomic_flagbool to indicate when the child thread should terminate its loop:
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdatomic.h>
#include <stdbool.h>
#include <stddef.h>
#include <threads.h>
atomic_bool flag = ATOMIC_VAR_INIT(false);
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 error */
}
/* ... */
/* Set flag when done */
atomic_store(&flag,flag = true);
return 0;
} |
Exceptions
CON37-C-EX1: Implementations such as POSIX that provide defined behavior when multithreaded programs use custom signal handlers are exempt from this rule [IEEE Std 1003.1-2013].
...
Mixing signals and threads causes undefined behavior 135.
Rule | Severity | Likelihood | Detectable |
|---|
Repairable | Priority | Level |
|---|---|---|
CON37-C | Low | Probable |
Yes | No |
P4 |
L3 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Automated Detection
| Tool | Version | Checker | Description | ||||||
|---|---|---|---|---|---|---|---|---|---|
| Astrée |
| stdlib-use-signal | Fully checked | ||||||
| CodeSonar |
| BADFUNC.SIGNAL | Use of signal | ||||||
| Coverity |
| MISRA C 2012 Rule 21.5 | Over-constraining | ||||||
| Cppcheck Premium |
| premium-cert-con37-c | |||||||
| Helix QAC |
| C5021 C++5022 | |||||||
| Klocwork |
| MISRA.STDLIB.SIGNAL | |||||||
| LDRA tool suite |
| 44 S | Enhanced enforcement | ||||||
| Parasoft C/C++test |
| CERT_C-CON37-a | The signal handling facilities of <signal.h> shall not be used | |||||||
| PC-lint Plus |
| 586 | Fully supported | ||||||
| Polyspace Bug Finder |
| CERT C: Rule CON37-C | Checks for signal call in multithreaded program (rule fully covered) | ||||||
| RuleChecker |
| stdlib-use-signal | Fully checked |
Bibliography
| [IEEE Std 1003.1-2013] | XSH 2.9.1, "Thread Safety" |
...
...