...
In this noncompliant code example, err_msg is updated to indicate that the SIGINT signal was delivered. Undefined behavior occurs if a SIGINT is generated before the allocation completes.
| 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;
}
|
...
Portably, signal handlers can only unconditionally get or set a flag of type volatile sig_atomic_t and return.
| 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;
}
|
...
The noncompliant code example below declares volatile an object with static storage duration that is accessed in the signal handler. However, since the type of the object is not sig_atomic_t, the behavior of the program is undefined. Note that the behavior of the program is undefined also because the handler for the SIGFPE signal returns. See undefined behavior 123 of Appendix J of C99.
| 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;
}
|
...