Signal file descriptors

#include <x/signalfd.H>

x::signalfd fd=x::signalfd::create();

fd->capture(SIGHUP);

fd->nonblock(true);

// ...

x::signalfd::getsignal_t gs=fd->getsignal();


if (gs.ssi_signo == SIGHUP)
    handle_sighup();

This is an implementation of signal file descriptors, a Linux kernel specific feature. A signal file descriptor enables the implementation of signal processing by reading a file descriptor in an orderly fashion, instead of installing an asynchronous signal handler, and being constrained by the reentrance requirements imposed on asynchronous signal handlers.

A x::signalfd is a file descriptor. The list of signals processed via the signal file descriptor must be explicitly declared by invoking capture() (and undone by uncapture(), if needed). Upon receipt of a signal, instead of interrupting the process and invoking a signal handler, the signal file descriptor becomes readable (and for that reason it's usually made non-blocking).

Reading from the underlying file descriptor returns a structure. This implementation provides a convenient wrapper, getsignal() that gives the structure read from the signal file descriptor. Of particular importance, its ssi_signo gives the signal number received by the process. The same signal file descriptor can capture multiple signals.

If no signals are pending for the process, getsignal() blocks until a capture signal gets delivered, if the signal file descriptor is blocking. getsignal() returns immediately for a non-blocking file descriptor, with the signal number given as 0.

Note

As noted by signalfd(2), signals must be blocked before they can be captured by a file descriptor, and any execution thread that does not have the signal blocked will catch the signal instead of it being reported via a signal file descriptor. Applications that use signal file descriptors should block them in main(), before starting any threads.