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.

Index

Types

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, // sig::ILL: illegal opcode
	ILLOPN = 2, // sig::ILL: illegal operand
	ILLADR = 3, // sig::ILL: illegal addressing mode
	ILLTRP = 4, // sig::ILL: illegal trap
	PRVOPC = 5, // sig::ILL: privileged opcode
	PRVREG = 6, // sig::ILL: privileged register
	COPROC = 7, // sig::ILL: coprocessor error
	BADSTK = 8, // sig::ILL: internal stack error
	INTDIV = 1, // sig::FPE: integer divide by zero
	INTOVF = 2, // sig::FPE: integer overflow
	FLTDIV = 3, // sig::FPE: floating-point divide by zero
	FLTOVF = 4, // sig::FPE: floating-point overflow
	FLTUND = 5, // sig::FPE: floating-point underflow
	FLTRES = 6, // sig::FPE: floating-point inexact result
	FLTINV = 7, // sig::FPE: invalid floating-point operation
	FLTSUB = 8, // sig::FPE: subscript out of range
	MAPERR = 1, // sig::SEGV: address not mapped to object
	ACCERR = 2, // sig::SEGV: invalid permissions for mapped object
	BNDERR = 3, // sig::SEGV: failed address bound checks
	PKUERR = 4, // sig::SEGV: access was denied by memory protection keys
	MTEAERR = 8, // sig::SEGV
	MTESERR = 9, // sig::SEGV
	ADRALN = 1, // sig::BUS: invalid address alignment
	ADRERR = 2, // sig::BUS: nonexistent physical address
	OBJERR = 3, // sig::BUS: object-specific hardware error
	MCEERR_AR = 4, // sig::BUS: hardware memory error consumed on a machine check; action required
	MCEERR_AO = 5, // sig::BUS: hardware memory error detected in process but not consumed; action optional
	BRKPT = 1, // sig::TRAP: process breakpoint
	TRACE = 2, // sig::TRAP: process trace trap
	BRANCH = 3, // sig::TRAP: process taken branch trap
	HWBKPT = 4, // sig::TRAP: hardware breakpoint/watchpoint
	UNK = 5, // sig::TRAP
	EXITED = 1, // sig::CHLD: child exited
	KILLED = 2, // sig::CHLD: child terminated abnormally without a core file
	DUMPED = 3, // sig::CHLD: child terminated abnormally with a core file
	TRAPPED = 4, // sig::CHLD: traced child has trapped
	STOPPED = 5, // sig::CHLD: child has stopped
	CONTINUED = 6, // sig::CHLD: stopped child has continued
	IN = 1, // sig::POLL: data input available
	OUT = 2, // sig::POLL: output buffers available
	MSG = 3, // sig::POLL: input message available
	ERR = 4, // sig::POLL: I/O error
	PRI = 5, // sig::POLL: high priority input available
	HUP = 6, // sig::POLL: device disconnected
};
type flag = enum {
	// For use with sig::CHLD. Prevents notifications when child processes
	// stop (e.g. via sig::STOP) or resume (i.e. sig::CONT).
	NOCLDSTOP = rt::SA_NOCLDSTOP: int,
	// For use with sig::CHLD. Do not transform children into zombies when
	// they terminate. Note that POSIX leaves the delivery of sig::CHLD
	// 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.
	RESETHAND = rt::SA_RESETHAND: int,
};
type handler = fn(sig: sig, info: *siginfo, ucontext: *opaque) void;
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.
};
type sig = enum {
	HUP = rt::SIGHUP, // Hangup.
	INT = rt::SIGINT, // Terminal interrupt.
	QUIT = rt::SIGQUIT, // Terminal quit.
	ILL = rt::SIGILL, // Illegal instruction.
	TRAP = rt::SIGTRAP, // Trace/breakpoint trap.
	ABRT = rt::SIGABRT, // Process abort.
	BUS = rt::SIGBUS, // Access to an undefined portion of a memory object.
	FPE = rt::SIGFPE, // Erroneous arithmetic operation.
	KILL = rt::SIGKILL, // Kill (cannot be caught or ignored).
	USR1 = rt::SIGUSR1, // User-defined signal 1.
	SEGV = rt::SIGSEGV, // Invalid memory reference.
	USR2 = rt::SIGUSR2, // User-defined signal 2.
	PIPE = rt::SIGPIPE, // Write on a pipe with no one to read it.
	ALRM = rt::SIGALRM, // Alarm clock.
	TERM = rt::SIGTERM, // Termination.
	CHLD = rt::SIGCHLD, // Child process terminated, stopped, or continued.
	CONT = rt::SIGCONT, // Continue executing if stopped.
	STOP = rt::SIGSTOP, // Stop executing (cannot be caught or ignored).
	TSTP = rt::SIGTSTP, // Terminal stop.
	TTIN = rt::SIGTTIN, // Background process attempting read.
	TTOU = rt::SIGTTOU, // Background process attempting write.
	URG = rt::SIGURG, // High bandwidth data is available at a socket.
	XCPU = rt::SIGXCPU, // CPU time limit exceeded.
	XFSZ = rt::SIGXFSZ, // File size limit exceeded.
	VTALRM = rt::SIGVTALRM, // Virtual timer expired.
	PROF = rt::SIGPROF, // Profiling timer expired.
	WINCH = rt::SIGWINCH, // Window resize signal.
	IO = rt::SIGIO, // I/O now possible (synonymous with sig::POLL).
	POLL = rt::SIGPOLL, // Pollable event.
	PWR = rt::SIGPWR, // Power failure.
	SYS = rt::SIGSYS, // Bad system call.
};
type siginfo = union {
	struct {
		// The signal number being delivered.
		signo: sig,
		// 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,
		union {
			struct {
				// Process ID of the sender.
				pid: int,
				// Real user ID of the sending process.
				uid: uint,
				// Exit value or signal.
				status: int,
			},
			struct {
				// Address of the faulting instruction.
				addr: *opaque,
			},
		},
	},
	// Pads the structure out to the length used by the kernel; do not use.
	_si_pad: [128 - 3 * size(int)]u8,
};

// Undocumented types:
type sigaction = rt::sigact;
type sigset = rt::sigset;

Functions

fn block(signals: sig...) sigset;
fn getprocmask() sigset;
fn handle(signum: sig, handler: *handler, opt: (flag | sigset)...) sigaction;
fn ignore(signum: sig) void;
fn newsigset(items: sig...) sigset;
fn read(fd: io::file) (siginfo | errors::error);
fn reset(signum: sig) void;
fn resetall() void;
fn restore(signum: sig, action: *sigaction) void;
fn setprocmask(how: how, mask: *sigset) sigset;
fn signalfd(signals: sig...) (io::file | errors::error);
fn signame(sig: sig) const str;
fn sigset_add(set: *sigset, items: sig...) void;
fn sigset_del(set: *sigset, items: sig...) void;
fn sigset_empty(set: *sigset) void;
fn sigset_member(set: *sigset, item: sig) bool;
fn unblock(signals: sig...) sigset;
fn update(fd: io::file, signals: sig...) (void | errors::error);

Types

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, // sig::ILL: illegal opcode
	ILLOPN = 2, // sig::ILL: illegal operand
	ILLADR = 3, // sig::ILL: illegal addressing mode
	ILLTRP = 4, // sig::ILL: illegal trap
	PRVOPC = 5, // sig::ILL: privileged opcode
	PRVREG = 6, // sig::ILL: privileged register
	COPROC = 7, // sig::ILL: coprocessor error
	BADSTK = 8, // sig::ILL: internal stack error
	INTDIV = 1, // sig::FPE: integer divide by zero
	INTOVF = 2, // sig::FPE: integer overflow
	FLTDIV = 3, // sig::FPE: floating-point divide by zero
	FLTOVF = 4, // sig::FPE: floating-point overflow
	FLTUND = 5, // sig::FPE: floating-point underflow
	FLTRES = 6, // sig::FPE: floating-point inexact result
	FLTINV = 7, // sig::FPE: invalid floating-point operation
	FLTSUB = 8, // sig::FPE: subscript out of range
	MAPERR = 1, // sig::SEGV: address not mapped to object
	ACCERR = 2, // sig::SEGV: invalid permissions for mapped object
	BNDERR = 3, // sig::SEGV: failed address bound checks
	PKUERR = 4, // sig::SEGV: access was denied by memory protection keys
	MTEAERR = 8, // sig::SEGV
	MTESERR = 9, // sig::SEGV
	ADRALN = 1, // sig::BUS: invalid address alignment
	ADRERR = 2, // sig::BUS: nonexistent physical address
	OBJERR = 3, // sig::BUS: object-specific hardware error
	MCEERR_AR = 4, // sig::BUS: hardware memory error consumed on a machine check; action required
	MCEERR_AO = 5, // sig::BUS: hardware memory error detected in process but not consumed; action optional
	BRKPT = 1, // sig::TRAP: process breakpoint
	TRACE = 2, // sig::TRAP: process trace trap
	BRANCH = 3, // sig::TRAP: process taken branch trap
	HWBKPT = 4, // sig::TRAP: hardware breakpoint/watchpoint
	UNK = 5, // sig::TRAP
	EXITED = 1, // sig::CHLD: child exited
	KILLED = 2, // sig::CHLD: child terminated abnormally without a core file
	DUMPED = 3, // sig::CHLD: child terminated abnormally with a core file
	TRAPPED = 4, // sig::CHLD: traced child has trapped
	STOPPED = 5, // sig::CHLD: child has stopped
	CONTINUED = 6, // sig::CHLD: stopped child has continued
	IN = 1, // sig::POLL: data input available
	OUT = 2, // sig::POLL: output buffers available
	MSG = 3, // sig::POLL: input message available
	ERR = 4, // sig::POLL: I/O error
	PRI = 5, // sig::POLL: high priority input available
	HUP = 6, // sig::POLL: device disconnected
};

A code indicating why a signal was sent.

type flag[link]

type flag = enum {
	// For use with sig::CHLD. Prevents notifications when child processes
	// stop (e.g. via sig::STOP) or resume (i.e. sig::CONT).
	NOCLDSTOP = rt::SA_NOCLDSTOP: int,
	// For use with sig::CHLD. Do not transform children into zombies when
	// they terminate. Note that POSIX leaves the delivery of sig::CHLD
	// 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.
	RESETHAND = rt::SA_RESETHAND: int,
};

Flags used to configure the behavior of a signal handler.

type handler[link]

type handler = fn(sig: sig, info: *siginfo, ucontext: *opaque) 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 sig[link]

type sig = enum {
	HUP = rt::SIGHUP, // Hangup.
	INT = rt::SIGINT, // Terminal interrupt.
	QUIT = rt::SIGQUIT, // Terminal quit.
	ILL = rt::SIGILL, // Illegal instruction.
	TRAP = rt::SIGTRAP, // Trace/breakpoint trap.
	ABRT = rt::SIGABRT, // Process abort.
	BUS = rt::SIGBUS, // Access to an undefined portion of a memory object.
	FPE = rt::SIGFPE, // Erroneous arithmetic operation.
	KILL = rt::SIGKILL, // Kill (cannot be caught or ignored).
	USR1 = rt::SIGUSR1, // User-defined signal 1.
	SEGV = rt::SIGSEGV, // Invalid memory reference.
	USR2 = rt::SIGUSR2, // User-defined signal 2.
	PIPE = rt::SIGPIPE, // Write on a pipe with no one to read it.
	ALRM = rt::SIGALRM, // Alarm clock.
	TERM = rt::SIGTERM, // Termination.
	CHLD = rt::SIGCHLD, // Child process terminated, stopped, or continued.
	CONT = rt::SIGCONT, // Continue executing if stopped.
	STOP = rt::SIGSTOP, // Stop executing (cannot be caught or ignored).
	TSTP = rt::SIGTSTP, // Terminal stop.
	TTIN = rt::SIGTTIN, // Background process attempting read.
	TTOU = rt::SIGTTOU, // Background process attempting write.
	URG = rt::SIGURG, // High bandwidth data is available at a socket.
	XCPU = rt::SIGXCPU, // CPU time limit exceeded.
	XFSZ = rt::SIGXFSZ, // File size limit exceeded.
	VTALRM = rt::SIGVTALRM, // Virtual timer expired.
	PROF = rt::SIGPROF, // Profiling timer expired.
	WINCH = rt::SIGWINCH, // Window resize signal.
	IO = rt::SIGIO, // I/O now possible (synonymous with sig::POLL).
	POLL = rt::SIGPOLL, // Pollable event.
	PWR = rt::SIGPWR, // Power failure.
	SYS = rt::SIGSYS, // Bad system call.
};

All possible signals.

type siginfo[link]

type siginfo = union {
	struct {
		// The signal number being delivered.
		signo: sig,
		// 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,
		union {
			struct {
				// Process ID of the sender.
				pid: int,
				// Real user ID of the sending process.
				uid: uint,
				// Exit value or signal.
				status: int,
			},
			struct {
				// Address of the faulting instruction.
				addr: *opaque,
			},
		},
	},
	// 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.

type sigaction[link]

Show undocumented member
type sigaction = rt::sigact;

type sigset[link]

Show undocumented member
type sigset = rt::sigset;

Functions

fn block[link]

fn block(signals: sig...) 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: sig, handler: *handler, opt: (flag | 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: sig) 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: sig...) 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: sig) void;

Unregisters signal handlers for the specified signal.

fn resetall[link]

fn resetall() void;

Unregisters all signal handlers.

fn restore[link]

fn restore(signum: sig, 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: sig...) (io::file | errors::error);

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

fn signame[link]

fn signame(sig: sig) const str;

Returns the human friendly name of a given signal.

fn sigset_add[link]

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

Adds signals to a sigset.

fn sigset_del[link]

fn sigset_del(set: *sigset, items: sig...) 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: sig) bool;

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

fn unblock[link]

fn unblock(signals: sig...) 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: sig...) (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.