liveBook · Manning

Signal

As explained in Modern C

An operating-system signal is an asynchronous notification delivered to a process to report an event or request handling.

A handler that records an interruption

A handler receives a signal number as an int. In the illustrated handler, SIGTERM calls quick_exit, SIGABRT calls _Exit, and SIGCONT returns when available. For other signals, the handler restores the default handling, records the signal number in an interrupt flag, and returns. The important move is to leave further handling to the interrupted program rather than do extensive work inside the handler. section 17.6 section 17.7

A signal redirects control flow when an exceptional event occurs. A synchronous signal is tied to a faulting instruction, such as erroneous arithmetic or invalid storage access. An asynchronous signal comes from an operating or runtime-system event, such as a termination request; it can arrive while execution is in an intermediate state. C signal handlers provide an abstraction for handling both kinds of event. section 17.6 section 17.0

The basic interface separates three jobs:

  • Install a handler with signal, supplying a signal number and a handler function. Check for SIG_ERR when installation fails; SIG_DFL and SIG_IGN represent default and ignored handling. section 17.6
  • Use raise to generate a signal from the program. section 17.6
  • Keep communication with a handler narrow: use volatile sig_atomic_t, atomic_flag, or another lock-free atomic type to pass information to or from it. section 17.7
143   /**
144    ** @brief A minimal signal handler
145    **
146    ** After updating the signal count, for most signals this
147    ** simply stores the signal value in "interrupt" and returns.
148    **/
149   static void signal_handler(int sig) {
150     sh_count(sig);
151     switch (sig) {
152     case SIGTERM: quick_exit(EXIT_FAILURE);
153     case SIGABRT: _Exit(EXIT_FAILURE);
154   #ifdef SIGCONT
155       // continue normal operation
156     case SIGCONT: return;
157   #endif
158     default:
159       /* reset the handling to its default */
160       signal(sig, SIG_DFL);
161       interrupt = sig;
162       return;
163     }
164   }


!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":0,\"ch\":0},{\"line\":0,\"ch\":3}],[{\"line\":1,\"ch\":0},{\"line\":1,\"ch\":3}],[{\"line\":2,\"ch\":0},{\"line\":2,\"ch\":3}],[{\"line\":3,\"ch\":0},{\"line\":3,\"ch\":3}],[{\"line\":4,\"ch\":0},{\"line\":4,\"ch\":3}],[{\"line\":5,\"ch\":0},{\"line\":5,\"ch\":3}],[{\"line\":6,\"ch\":0},{\"line\":6,\"ch\":3}],[{\"line\":6,\"ch\":6},{\"line\":6,\"ch\":17}],[{\"line\":6,\"ch\":18},{\"line\":6,\"ch\":32}],[{\"line\":4,\"ch\":45},{\"line\":4,\"ch\":48}],[{\"line\":6,\"ch\":33},{\"line\":6,\"ch\":36}],[{\"line\":18,\"ch\":10},{\"line\":18,\"ch\":13}],[{\"line\":7,\"ch\":0},{\"line\":7,\"ch\":3}],[{\"line\":7,\"ch\":8},{\"line\":7,\"ch\":16}],[{\"line\":8,\"ch\":0},{\"line\":8,\"ch\":3}],[{\"line\":8,\"ch\":8},{\"line\":8,\"ch\":14}],[{\"line\":9,\"ch\":0},{\"line\":9,\"ch\":3}],[{\"line\":9,\"ch\":8},{\"line\":9,\"ch\":12}],[{\"line\":10,\"ch\":8},{\"line\":10,\"ch\":12}],[{\"line\":13,\"ch\":8},{\"line\":13,\"ch\":12}],[{\"line\":9,\"ch\":13},{\"line\":9,\"ch\":20}],[{\"line\":9,\"ch\":22},{\"line\":9,\"ch\":32}],[{\"line\":9,\"ch\":33},{\"line\":9,\"ch\":45}],[{\"line\":10,\"ch\":28},{\"line\":10,\"ch\":40}],[{\"line\":10,\"ch\":0},{\"line\":10,\"ch\":3}],[{\"line\":9,\"ch\":8},{\"line\":9,\"ch\":12}],[{\"line\":10,\"ch\":8},{\"line\":10,\"ch\":12}],[{\"line\":13,\"ch\":8},{\"line\":13,\"ch\":12}],[{\"line\":10,\"ch\":13},{\"line\":10,\"ch\":20}],[{\"line\":10,\"ch\":22},{\"line\":10,\"ch\":27}],[{\"line\":9,\"ch\":33},{\"line\":9,\"ch\":45}],[{\"line\":10,\"ch\":28},{\"line\":10,\"ch\":40}],[{\"line\":11,\"ch\":0},{\"line\":11,\"ch\":3}],[{\"line\":11,\"ch\":6},{\"line\":11,\"ch\":12}],[{\"line\":12,\"ch\":0},{\"line\":12,\"ch\":3}],[{\"line\":13,\"ch\":0},{\"line\":13,\"ch\":3}],[{\"line\":9,\"ch\":8},{\"line\":9,\"ch\":12}],[{\"line\":10,\"ch\":8},{\"line\":10,\"ch\":12}],[{\"line\":13,\"ch\":8},{\"line\":13,\"ch\":12}],[{\"line\":4,\"ch\":60},{\"line\":4,\"ch\":66}],[{\"line\":13,\"ch\":22},{\"line\":13,\"ch\":28}],[{\"line\":19,\"ch\":10},{\"line\":19,\"ch\":16}],[{\"line\":14,\"ch\":0},{\"line\":14,\"ch\":3}],[{\"line\":14,\"ch\":6},{\"line\":14,\"ch\":12}],[{\"line\":15,\"ch\":0},{\"line\":15,\"ch\":3}],[{\"line\":15,\"ch\":8},{\"line\":15,\"ch\":15}],[{\"line\":16,\"ch\":39},{\"line\":16,\"ch\":46}],[{\"line\":16,\"ch\":0},{\"line\":16,\"ch\":3}],[{\"line\":17,\"ch\":0},{\"line\":17,\"ch\":3}],[{\"line\":1,\"ch\":27},{\"line\":1,\"ch\":33}],[{\"line\":3,\"ch\":29},{\"line\":3,\"ch\":35}],[{\"line\":4,\"ch\":28},{\"line\":4,\"ch\":34}],[{\"line\":6,\"ch\":18},{\"line\":6,\"ch\":24}],[{\"line\":17,\"ch\":10},{\"line\":17,\"ch\":16}],[{\"line\":17,\"ch\":22},{\"line\":17,\"ch\":29}],[{\"line\":18,\"ch\":0},{\"line\":18,\"ch\":3}],[{\"line\":19,\"ch\":0},{\"line\":19,\"ch\":3}],[{\"line\":4,\"ch\":60},{\"line\":4,\"ch\":66}],[{\"line\":13,\"ch\":22},{\"line\":13,\"ch\":28}],[{\"line\":19,\"ch\":10},{\"line\":19,\"ch\":16}],[{\"line\":20,\"ch\":0},{\"line\":20,\"ch\":3}],[{\"line\":21,\"ch\":0},{\"line\":21,\"ch\":3}]]"}
!@%STYLE%@!

The handler listing makes the control-flow choices concrete: immediate exit for two signals, return for another, and a recorded interruption followed by return in the default branch. section 17.6

TAKEAWAY: A handler should usually mark the interrupt condition and return, so the interrupted context can deal with it. Do not assume every signal can be handled in the same way: the example’s attempt to install a handler for SIGKILL fails, and some signal names are included only when the platform provides them. section 17.7 section 17.6

How Modern C covers it

How deep it goes
Defines synchronous and asynchronous events and works through handler registration and behavior, while treating C’s signal interface as rudimentary.
Examples
Uses a handler that branches on SIGTERM, SIGABRT, and SIGCONT, plus installation output showing a failed SIGKILL registration.
What it assumes
Assumes familiarity with C functions and control flow, while defining synchronous and asynchronous interrupts before explaining handlers.
What you can do after
Apply it via C’s signal interface to install a handler and defer most interrupt handling to the interrupted context.
How it connects
Connects signals to control flow, interrupts, setjmp/longjmp, and lock-free atomic types.

Also explained in

Compare how 3 books explain signal →

Related concepts

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