libslack(sig) - ISO C compliant signal handling module
#include <slack/std.h> #include <slack/sig.h> typedef void signal_handler_t(int signo); int signal_set_handler(int signo, int flags, signal_handler_t *handler); int signal_addset(int signo_handled, int signo_blocked); int signal_received(int signo); int signal_raise(int signo); int signal_handle(int signo); void signal_handle_all(void);
This module provides functions for ISO C compliant signal handling. ISO C compliant signal handlers may only set a single value of type sig_atomic_t. This is a very restrictive requirement. This module allows you to specify unrestricted signal handlers while (almost) transparently enforcing ISO C compliance.
When a handled signal arrives, an ISO C compliant signal handler is invoked to merely record the fact that the signal was received. Then, in the main thread of execution, when signal_handle(3) or signal_handle_all(3) is invoked, the client supplied signal handlers for all signals received since the last invocation of signal_handle(3) or signal_handle_all(3) are invoked.
Since the user supplied signal handlers execute in the main thread on execution, they are not subject to the normal restrictions on signal handlers. Also, they will execute with the same signals blocked as the real signal handler.
int signal_set_handler(int signo, int flags, signal_handler_t *handler)
Installs handler
as the signal handler for the signal signo
. flags
is used as the sa_flags field of the real_signal_handler_t argument to
sigaction(2). The actual function set as the signal handler is not
handler
. It is an ISO C compliant function that just records the fact
that a signal was received. handler
will only be invoked when the client
invokes signal_handle(3) or signal_handle_all(3) from the main thread
of execution. So there are no restrictions on handler
. When handler
is
invoked, the signo
signal will be blocked. Other signals can also be
blocked when handler
is invoked using signal_addset(3). Several
signals do not allow such treatment. Behaviour upon return from their
handlers is undefined (or defined, but not very pleasant). They are
SIGILL
, SIGABRT
, SIGFPE
, SIGBUS
, SIGSEGV
and SIGSYS
.
Handlers supplied for these signals are installed as the real signal
handlers. On success, returns 0
. On error, returns -1
with errno
set appropriately.
int signal_addset(int signo_handled, int signo_blocked)
Adds signo_blocked
to the set of signals that will be blocked when the
handler for signal signo_handled
is invoked. This must not be called
before the call to signal_set_handler(3) for signo_handled
which
initialises the signal set to include signo_handled
. On success, returns
0
. On error, returns -1
with errno
set appropriately.
int signal_received(int signo)
Returns the number of times that the signal signo
has been received since
the last call to signal_handle(3) with signo
as its argument
or signal_handle_all(3). On error (i.e. signo
is out of
range), returns -1
and sets errno
set to EINVAL
.
int signal_raise(int signo)
Simulates the receipt of the signal specified by signo
. On success,
returns the number of unhandled signo
signals (including this one). On
error (i.e. if signo
is out of range), returns -1
and sets errno
to
EINVAL
.
int signal_handle(int signo)
Executes the installed signal handler for the signal signo
. The signo
signal (and any others added with signal_addset(3)) is blocked during the
execution of the signal handler. Clears the received status of the signo
signal. On success, returns 0
. On error, returns -1
with errno
set
appropriately.
void signal_handle_all(void)
Executes the installed signal handlers for all signals that have been received since the last call to signal_handle(3) or signal_handle_all(3). During the execution of each signal handler, the corresponding signal (and possibly others) will be blocked. Clears the received status of all signals handled.
EINVAL
When a signal number argument is out of range.
Unsafe
#include <slack/std.h> #include <slack/sig.h> void hup(int signo) { printf("SIGHUP received\n"); } void term(int signo) { printf("SIGTERM received\n"); exit(EXIT_SUCCESS); } int main(int ac, char **av) { if (signal_set_handler(SIGHUP, 0, hup) == -1) return EXIT_FAILURE; if (signal_set_handler(SIGTERM, 0, term) == -1) return EXIT_FAILURE; for (;;) { char mesg[BUFSIZ]; ssize_t n; signal_handle_all(); // Signals arriving here are lost while ((n = read(STDIN_FILENO, mesg, BUFSIZ)) > 0) fprintf(stderr, "%*.*s", n, n, mesg); if (n == -1 && errno == EINTR) continue; exit((n == -1) ? EXIT_FAILURE : EXIT_SUCCESS); return EXIT_SUCCESS; }
libslack(3), prog(3)
20100612 raf <raf@raf.org>