unix::signal+x86_64 +linux

The signal module provides support for Unix signal handlers. Typical applications will provide a signal handler to handle to configure it for the desired signal, possibly along with flags and a signal mask. This function returns the previous signal handler, which can be passed to restore to restore the previous behavior.

Signal handling is stupidly complicated and easy to get wrong. The standard library makes little effort to help you deal with this. Consult your local man pages, particularly signal-safety(7) on Linux, and perhaps a local priest as well. We advise you to get out of the signal handler as soon as possible, for example via the "self-pipe trick".

Note that the necessary sa_restorer functionality is implemented (and imposed) by the standard library.



type code;
type flags;
type handler;
type how;
type siginfo;

// Undocumented types:
type sigaction;
type signal;
type sigset;


const SIGABRT: signal;
const SIGALRM: signal;
const SIGBUS: signal;
const SIGCHLD: signal;
const SIGCONT: signal;
const SIGFPE: signal;
const SIGHUP: signal;
const SIGILL: signal;
const SIGINT: signal;
const SIGIO: signal;
const SIGKILL: signal;
const SIGPIPE: signal;
const SIGPOLL: signal;
const SIGPROF: signal;
const SIGPWR: signal;
const SIGQUIT: signal;
const SIGSEGV: signal;
const SIGSTOP: signal;
const SIGSYS: signal;
const SIGTERM: signal;
const SIGTRAP: signal;
const SIGTSTP: signal;
const SIGTTIN: signal;
const SIGTTOU: signal;
const SIGURG: signal;
const SIGUSR1: signal;
const SIGUSR2: signal;
const SIGVTALRM: signal;
const SIGWINCH: signal;
const SIGXCPU: signal;
const SIGXFSZ: signal;


fn block(signal...) sigset;
fn getprocmask() sigset;
fn handle(signal, *handler, (flags | sigset)...) sigaction;
fn ignore(signal) void;
fn newsigset(signal...) sigset;
fn read(io::file) (siginfo | errors::error);
fn reset(signal) void;
fn resetall() void;
fn restore(signal, *sigaction) void;
fn setprocmask(how, *sigset) sigset;
fn signalfd(signal...) (io::file | errors::error);
fn signame(signal) const str;
fn sigset_add(*sigset, signal...) void;
fn sigset_del(*sigset, signal...) void;
fn sigset_empty(*sigset) void;
fn sigset_member(*sigset, signal) bool;
fn unblock(signal...) sigset;
fn update(io::file, signal...) (void | errors::error);


type code[link]

type code = enum {
	USER = 0, // sent by userspace program (kill)
KERNEL = 128, // sent by kernel
QUEUE = -1, // sent by sigqueue
TIMER = -2, // generated by expiration of a timer
MESQ = -3, // generated by arrival of a message on an empty queue
ASYNCIO = -4, // generated by completion of an asynchronous I/O request
SIGIO = -5, TKILL = -6, // sent by userspace program (tkill, tgkill)
ASYNCNL = -60, ILLOPC = 1, // SIGILL: illegal opcode
ILLOPN = 2, // SIGILL: illegal operand
ILLADR = 3, // SIGILL: illegal addressing mode
ILLTRP = 4, // SIGILL: illegal trap
PRVOPC = 5, // SIGILL: privileged opcode
PRVREG = 6, // SIGILL: privileged register
COPROC = 7, // SIGILL: coprocessor error
BADSTK = 8, // SIGILL: internal stack error
INTDIV = 1, // SIGFPE: integer divide by zero
INTOVF = 2, // SIGFPE: integer overflow
FLTDIV = 3, // SIGFPE: floating-point divide by zero
FLTOVF = 4, // SIGFPE: floating-point overflow
FLTUND = 5, // SIGFPE: floating-point underflow
FLTRES = 6, // SIGFPE: floating-point inexact result
FLTINV = 7, // SIGFPE: invalid floating-point operation
FLTSUB = 8, // SIGFPE: subscript out of range
MAPERR = 1, // SIGSEGV: address not mapped to object
ACCERR = 2, // SIGSEGV: invalid permissions for mapped object
BNDERR = 3, // SIGSEGV: failed address bound checks
PKUERR = 4, // SIGSEGV: access was denied by memory protection keys
ADRALN = 1, // SIGBUS: invalid address alignment
ADRERR = 2, // SIGBUS: nonexistent physical address
OBJERR = 3, // SIGBUS: object-specific hardware error
MCEERR_AR = 4, // SIGBUS: hardware memory error consumed on a machine check; action required
MCEERR_AO = 5, // SIGBUS: hardware memory error detected in process but not consumed; action optional
BRKPT = 1, // SIGTRAP: process breakpoint
TRACE = 2, // SIGTRAP: process trace trap
BRANCH = 3, // SIGTRAP: process taken branch trap
HWBKPT = 4, // SIGTRAP: hardware breakpoint/watchpoint
EXITED = 1, // SIGCHLD: child exited
KILLED = 2, // SIGCHLD: child terminated abnormally without a core file
DUMPED = 3, // SIGCHLD: child terminated abnormally with a core file
TRAPPED = 4, // SIGCHLD: traced child has trapped
STOPPED = 5, // SIGCHLD: child has stopped
CONTINUED = 6, // SIGCHLD: stopped child has continued
IN = 1, // SIGPOLL: data input available
OUT = 2, // SIGPOLL: output buffers available
MSG = 3, // SIGPOLL: input message available
ERR = 4, // SIGPOLL: I/O error
PRI = 5, // SIGPOLL: high priority input available
HUP = 6, // SIGPOLL: device disconnected

A code indicating why a signal was sent.

type flags[link]

type flags = enum {
	// For use with [[SIGCHLD]]. Prevents notifications when child processes
// stop (e.g. via [[SIGSTOP]]) or resume (i.e. [[SIGCONT]]).
NOCLDSTOP = rt::SA_NOCLDSTOP: int, // For use with [[SIGCHLD]]. Do not transform children into zombies when
// they terminate. Note that POSIX leaves the delivery of [[SIGCHLD]]
// unspecified when this flag is present; some systems will still
// deliver a signal and others may not.
NOCLDWAIT = rt::SA_NOCLDWAIT: int, // Uses an alternate stack when handling this signal. See
// [[setaltstack]] and [[getaltstack]] for details.
ONSTACK = rt::SA_ONSTACK: int, // Makes certain system calls restartable across signals. See signal(7)
// or similar documentation for your local system for details.
RESTART = rt::SA_RESTART: int, // Do not add the signal to the signal mask while executing the signal
// handler. This can cause the same signal to be delivered again during
// the execution of the signal handler.
NODEFER = rt::SA_NODEFER: int, // Restore the signal handler to the default behavior upon entering the
// signal handler.

Flags used to configure the behavior of a signal handler.

type handler[link]

type handler = fn(sig: int, info: *siginfo, ucontext: *void) void;

A function which handles a signal. The first argument is the signal number which was caught, the second provides information about the signal, and the third argument is the ucontext, which is usually ignored by most signal handlers.

type how[link]

type how = enum {
	BLOCK = rt::SIG_BLOCK, // Adds the given set of signals to the current mask.
UNBLOCK = rt::SIG_UNBLOCK, // Removes the given set of signals from the current mask.
SETMASK = rt::SIG_SETMASK, // Sets the process mask to the given set.

Defines the modes of operation for setprocmask.

type siginfo[link]

type siginfo = union {
	struct {
		// The signal number being delivered.
signo: signal, // The errno, if any, associated with this signal. See
// [[errors::errno]] to convert to a Hare-native error.
errno: rt::errno, // The signal code, if any.
code: code, }, // Pads the structure out to the length used by the kernel; do not use.
_si_pad: [128 - 3 * size(int)]u8, };

Provides additional information about signal deliveries. Only the members defined by POSIX are available here; cast to rt::siginfo to access non-portable members.

TODO: Expand this with more portable options

type sigaction[link]

Show undocumented member
type sigaction = rt::sigact;

type signal[link]

Show undocumented member
type signal = int;

type sigset[link]

Show undocumented member
type sigset = rt::sigset;


def SIGABRT[link]

def SIGABRT: signal;

Process abort signal.

def SIGALRM[link]

def SIGALRM: signal;

Alarm clock.

def SIGBUS[link]

def SIGBUS: signal;

Access to an undefined portion of a memory object.

def SIGCHLD[link]

def SIGCHLD: signal;

Child process terminated, stopped, or continued.

def SIGCONT[link]

def SIGCONT: signal;

Continue executing, if stopped.

def SIGFPE[link]

def SIGFPE: signal;

Erroneous arithmetic operation.

def SIGHUP[link]

def SIGHUP: signal;


def SIGILL[link]

def SIGILL: signal;

Illegal instruction.

def SIGINT[link]

def SIGINT: signal;

Terminal interrupt signal.

def SIGIO[link]

def SIGIO: signal;

I/O now possible.

def SIGKILL[link]

def SIGKILL: signal;

Kill (cannot be caught or ignored).

def SIGPIPE[link]

def SIGPIPE: signal;

Write on a pipe with no one to read it.

def SIGPOLL[link]

def SIGPOLL: signal;

Pollable event.

def SIGPROF[link]

def SIGPROF: signal;

Profiling timer expired.

def SIGPWR[link]

def SIGPWR: signal;

Power failure.

def SIGQUIT[link]

def SIGQUIT: signal;

Terminal quit signal.

def SIGSEGV[link]

def SIGSEGV: signal;

Invalid memory reference.

def SIGSTOP[link]

def SIGSTOP: signal;

Stop executing (cannot be caught or ignored).

def SIGSYS[link]

def SIGSYS: signal;

Bad system call.

def SIGTERM[link]

def SIGTERM: signal;

Termination signal.

def SIGTRAP[link]

def SIGTRAP: signal;

Trace/breakposignal trap.

def SIGTSTP[link]

def SIGTSTP: signal;

Terminal stop signal.

def SIGTTIN[link]

def SIGTTIN: signal;

Background process attempting read.

def SIGTTOU[link]

def SIGTTOU: signal;

Background process attempting write.

def SIGURG[link]

def SIGURG: signal;

High bandwidth data is available at a socket.

def SIGUSR1[link]

def SIGUSR1: signal;

User-defined signal 1.

def SIGUSR2[link]

def SIGUSR2: signal;

User-defined signal 2.

def SIGVTALRM[link]

def SIGVTALRM: signal;

Virtual timer expired.

def SIGWINCH[link]

def SIGWINCH: signal;

Window resize signal.

def SIGXCPU[link]

def SIGXCPU: signal;

CPU time limit exceeded.

def SIGXFSZ[link]

def SIGXFSZ: signal;

File size limit exceeded.


fn block[link]

fn block(signals: signal...) sigset;

Adds the given list of signals to the process's current signal mask, returning the old signal mask. This is a convenience function around setprocmask.

fn getprocmask[link]

fn getprocmask() sigset;

Gets the current process's signal mask.

fn handle[link]

fn handle(signum: signal, handler: *handler, opt: (flags | sigset)...) sigaction;

Configures a new signal handler, returning the old details (which can be passed to restore to restore its behavior).

The variadic parameters specify either flags to enable or a signal mask to use via sigset; if the latter is provided no more than one may be used.

fn ignore[link]

fn ignore(signum: signal) void;

Prevents given signal from arriving to the current process. One common use case is to ignore SIGCHLD to avoid zombie child processes.

fn newsigset[link]

fn newsigset(items: signal...) sigset;

Creates a new signal set filled in with the provided signals (or empty if none are provided).

fn read[link]

fn read(fd: io::file) (siginfo | errors::error);

Reads pending signal info from a signalfd.

fn reset[link]

fn reset(signum: signal) void;

Unregisters signal handlers for the specified signal.

fn resetall[link]

fn resetall() void;

Unregisters all signal handlers.

fn restore[link]

fn restore(signum: signal, action: *sigaction) void;

Restores previous signal behavior following handle.

fn setprocmask[link]

fn setprocmask(how: how, mask: *sigset) sigset;

Sets the process's signal mask, returning the previous mask.

fn signalfd[link]

fn signalfd(signals: signal...) (io::file | errors::error);

Creates a signal file that handles the given set of signals.

fn signame[link]

fn signame(sig: signal) const str;

Returns the human friendly name of a given signal.

fn sigset_add[link]

fn sigset_add(set: *sigset, items: signal...) void;

Adds signals to a sigset.

fn sigset_del[link]

fn sigset_del(set: *sigset, items: signal...) void;

Removes signals from a sigset.

fn sigset_empty[link]

fn sigset_empty(set: *sigset) void;

Sets a sigset to empty.

fn sigset_member[link]

fn sigset_member(set: *sigset, item: signal) bool;

Returns true if the given signal is a member of this sigset.

fn unblock[link]

fn unblock(signals: signal...) sigset;

Removes the given list of signals from the process's current signal mask, returning the old signal mask. This is a convenience function around setprocmask.

fn update[link]

fn update(fd: io::file, signals: signal...) (void | errors::error);

Updates a signalfd with a new set of signals. The signal set is overwritten, rather than appended to, with the provided set of signals.