liveBook · Manning

Sig_atomic_t

As explained in Modern C, Third Edition

sig_atomic_t is an integer type whose object evaluation and assignment operations are guaranteed to be indivisible with respect to signal handling.

Record a signal, then return

A handler can record which signal arrived without processing it immediately: volatile sig_atomic_t interrupt = 0; void signal_handler(int sig) { interrupt = sig; } The interrupted code can inspect `interrupt` after the handler returns and handle the condition there. section 19.6 section 19.7

`sig_atomic_t` is an integer type whose object evaluations (loads) and assignments (stores) are uninterruptible with respect to signal handling: each appears either not to have started or to be complete. This does not mean the runtime must perform it in one undivided step. The type has a minimum width of eight bits, so do not assume it can hold a large count. section 19.6

TAKEAWAY: Use it as a flag, not as a counter.

  • A load or assignment has the stated guarantee; `++interrupt` does not. Increment can involve a separate load, increment, and store, and may overflow. section 19.6
  • For communication with an asynchronous signal handler, use `volatile sig_atomic_t` or an available `atomic_flag` or other lock-free atomic type. Keep the handler’s work minimal. section 19.7
 #if ATOMIC_LONG_LOCK_FREE > 1
 /**
  ** @brief Keep track of the number of calls into a
  **  signal handler for each possible signal.
  **
  ** Don't use this array directly.
  **
  ** @see sh_count to update this information.
  ** @see SH_PRINT to use that information.
  **/
 extern _Atomic(unsigned long) sh_counts[];
 
 /**
  ** @brief Use this in your signal handler to keep track of the
  ** number of calls to the signal @a sig.
  **
  ** @see sh_counted to use that information.
  **/
 inline
 void sh_count(int sig) {
   if (sig < sh_known) ++sh_counts[sig];
 }
 
 inline
 unsigned long sh_counted(int sig){
   return (sig < sh_known) ? sh_counts[sig] : 0;
 }
 
 #else

The lock-free atomic counter illustrates an alternative when a handler must count calls rather than merely record a signal. section 19.6

How Modern C, Third Edition covers it

How deep it goes
Defines uninterruptible loads and stores, then explains why increment is unsafe; does not develop sig_atomic_t beyond its restricted guarantees.
Examples
Contrasts storing a signal number in a flag with incrementing a counter, and shows a lock-free atomic counter alternative.
What it assumes
Assumes C assignment and signal-handler context while defining uninterruptible operations at the point they matter.
What you can do after
Build a minimal signal handler from scratch that records a signal number in a volatile sig_atomic_t flag.
How it connects
Connects signal handlers and asynchronous signals with volatile qualification, atomic_flag, and lock-free atomic types.

Also explained in

Compare how 2 books explain sig_atomic_t →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Modern C, Third Edition. The section links point to the parts of the book it draws on.