NAME

libslack(sig) - ISO C compliant signal handling module


SYNOPSIS

    #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);


DESCRIPTION

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.


ERRORS

EINVAL

When a signal number argument is out of range.


MT-Level

Unsafe


EXAMPLE

    #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;
    }


SEE ALSO

libslack(3), prog(3)


AUTHOR

20100612 raf <raf@raf.org>