Exactly what variables should be sig_atomic_t in the context of signal processing?

Here is a simple toy that uses volatile sig_atomic_t .

 #include <stdio.h> #include <signal.h> #include <stdlib.h> #include <unistd.h> #define UNUSED(x) (void) (x) volatile sig_atomic_t quit; void sigusr1_handler(int sig) { UNUSED(sig); write(1, "handler\n", 8); quit = 1; } int main() { struct sigaction sa; sa.sa_handler = sigusr1_handler; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); if (sigaction(SIGUSR1, &sa, NULL) == -1) { perror("sigaction"); return 1; } quit = 0; while (!quit) ; printf("Exiting ...\n"); return 0; } 

I think I know why volatile sig_atomic_t needed for the quit variable in this particular program.

  • Without volatile compiler can optimize while (!quit) ; to an endless cycle. It does not find a loop modifying quit , so it assumes that quit always remains 0 .
  • Updating in quit or reading quit should occur in one machine instruction. If several machine instructions are required to update or read quit , then if a signal handler is called during the update, reading in the signal handler may see an inconsistent value in quit .

Still correcting? If not, please correct me in your answer.

Now I want to study a general rule when sig_atomic_t necessary in the context of signal processing. Jonathan Leffler explained in a comment that it is not easy to provide generalization.

Can you provide a list of known scenarios where the variable should be defined as sig_atomic_t from the standard C point? This should not be an exhaustive list. It could be a list that a less experienced developer might turn to when writing C software with signal processing code.

+2
c signals
source share
1 answer

Can you provide a list of known scenarios where the variable should be defined as sig_atomic_t in terms of C?

There are 2 relevant sections from the c99 specification :

(ยง7.14, p2)
[Type sig_atomic_t ] is a (possibly volatile-qualified) integer type of object that can be accessed as an atomic object, even if there are asynchronous interrupts

(ยง7.14.1.1 p5)
If the signal occurs differently than by calling the abort or raise function, the behavior is undefined if the signal handler refers to any object with a static storage duration other than assigning a value to the object declared as volatile sig_atomic_t , ...

"Static storage duration" is defined as:

(ยง6.2.4, p3)
An object whose identifier is declared with external or internal communication, or with the storage class specifier static has a static storage duration. Its lifetime is the full execution of the program, and its stored value is initialized only once, before the program starts.

In a nutshell, you need to use volatile sig_atomic_t if the variable can be accessed asynchronously (i.e. the variable is accessed both inside and outside the signal handler). In addition, undefined behavior has access to the non volatile sig_atomic_t variable, which has a static storage duration. The behavior of undefined means that not only the value of the variable may be incompatible, the program can do something completely different (for example, segfault).

+1
source share

All Articles