An asynchronous signal handler must not access or change program state in an uncontrolled way. A function it can call without doing so is *asynchronous signal safe*. Do not infer this property from an ordinary function interface: the C standard guarantees it for only a few functions. section 19.6
The standard’s stated guarantees include:
- The terminating functions `abort`, `_Exit`, and `quick_exit`. Unlike `quick_exit`, `exit` cannot be called from an asynchronous signal handler. section 19.6
- `signal` when used for the same signal number that invoked the handler. section 19.6
- Certain operations on atomic objects. section 19.6
TAKEAWAY: Unless specified otherwise, a C library function is not asynchronous signal safe. In particular, an asynchronous signal handler cannot perform I/O under the C standard’s guarantees; platform-specific allowances do not establish portability. section 19.6
#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 `sh_count` listing uses an atomic counter to record handler calls, but compiles that implementation only when its lock-free condition holds. section 19.6

