...
Noncompliant Code Example
This code raises sets a signal within handler, while also setting a child thread to do work. This is meant to terminate the program, but results in undefined behavior.
Code Block | ||||
---|---|---|---|---|
| ||||
volatile sig_atomic_t flag = 0; void handler(int signum) { flag = 1; } void func(void *data) { /*/ ... */ if (thread_should_exit) {keep running until user sends SIGUSR1 while raise( SIGTERM!flag); // Undefined! { } /* ... */ } } int main(void) { signal(SIGUSR1, handler); // Undefined! int result; thrd_t thread; int result; if ((result = thrd_create(&tid, func, NULL)) != thrd_success) { /* Handle Error */ } /* ... */ return 0; } |
Compliant Solution
This code terminates the child thread rather than raising a signal. This has the same effect as the noncompliant code example, but is well-defined in C11dispenses with the signal handler, and uses an atomic_flag
to indicate when the child thread should terminate its loop.
Code Block | ||||
---|---|---|---|---|
| ||||
atomic_flag flag = ATOMIC_VAR_INIT; void func(void *data) { /*/ ... */ if (thread_should_exit) {keep running until user sends SIGUSR1 while thrd_exit(0!flag); // OK{ } /* ... */ } } int main(void) { int result; thrd_t thread; int result; if ((result = thrd_create(&tid, func, NULL)) != thrd_success) { /* Handle Error */ } /* ... */ /* Set flag when done */ while (!atomic_flag_test_and_set( &flag)) { /* try again */ } return 0; } |
Exceptions
CON37:EX0: Platforms that provide defined behavior when multithreaded programs use custom signal handlers are exempt from this rule. This would include POSIX, for example.
...