Sometimes, an ISR or signal handler may want to share a data structure with the “regular” part of a program. Such a data structure can range from simple constructs like screen size (SIGWINCH) to complex ones like a FIFO.
If there is no way to block interrupts or signals temporarily, then the only solution is to have the “regular” part of a program block an ISR or signal handler from touching a data structure if it is already in use by the regular part. Before accessing (read or write), the regular part of a program sets a flag that is of the type sig_atomic_t. If an interrupt or signal happens, and the handler sees that this flag is set, then it has to play by the rules and not access the data structure. Of course, when the operation is done, the regular part of the program also needs to clear the flag to indicate the data structure is free again.
This solution is usually unreasonable because it means data or updates will be lost if an ISR or signal handler cannot access a data structure that is in use.
A more common solution (on most platforms) is to temporarily block signals or interrupts. Blocking interrupts cannot be done in a user application (and for good reasons, too!). However, blocking (certain) signals can be done using the sigprocmask call, in conjunction with sigemptyset, sigfillset, sigaddset, sigdelset, and sigismember.
The general (and lazy) method is as follows:
This approach is quick-and-dirty because there may be some blocked signals from before this code. If a signal was blocked already, and is also specified in this code, then the last call will unblock it. This is usually undesirable because this code has a side effect that changes the blocked signals from the caller’s perspective.
A better approach is to remember what signals are already blocked, and only unblock the ones that the criticial section needs to block in addition to the signals already blocked.