Module signal

signal
Stability: unstable — the `Signal` enum and `on_signal`/`off_signal` are a thin typed face over `std/sys/signal`, and the handler shape is what has to change. `SignalHandler` is a bare `fn(data : *(u8)) -> unit`: it takes a raw pointer because there is nothing else a C signal handler can be handed, which means a Yo caller cannot close over anything and has to reach for a module-level global instead. It is also genuinely async-signal-unsafe territory — almost nothing in `std` may be called from inside one. The shape this wants is the one every event loop uses: deliver signals as EVENTS on the `Io` loop, so a handler is ordinary Yo code running between turns rather than in signal context. `std/sys/events` already has the machinery. Freezing the callback form would standardise the wrong one. — stable modules only change additively; this one may still change.

High-level signal handling.

Wraps std/sys/signal with a typed Signal enum.

Example

{ on_signal, off_signal, Signal, SignalHandler } :: import "std/signal";

handler :: (fn(data: *(u8)) -> unit)({ println("Caught SIGINT"); });
on_signal(.Interrupt, handler);

Stability

unstable — the Signal enum and on_signal/off_signal are a thin typed face over std/sys/signal, and the handler shape is what has to change. SignalHandler is a bare fn(data : *(u8)) -> unit: it takes a raw pointer because there is nothing else a C signal handler can be handed, which means a Yo caller cannot close over anything and has to reach for a module-level global instead. It is also genuinely async-signal-unsafe territory — almost nothing in std may be called from inside one.

The shape this wants is the one every event loop uses: deliver signals as EVENTS on the Io loop, so a handler is ordinary Yo code running between turns rather than in signal context. std/sys/events already has the machinery. Freezing the callback form would standardise the wrong one.

Types

Signal enum
Signal

Portable signal identifiers.

Variants

VariantFieldsDescription
Interrupt

SIGINT — interrupt from keyboard (Ctrl-C).

Terminate

SIGTERM — termination request.

Hangup

SIGHUP — terminal hangup.

User1

SIGUSR1 — user-defined signal 1.

User2

SIGUSR2 — user-defined signal 2.

Pipe

SIGPIPE — broken pipe.

Alarm

SIGALRM — timer alarm.

Child

SIGCHLD — child process status change.

SignalHandler type-alias
fn(data : *(u8)) -> unit

The shape of a signal handler: (data : *u8) -> unit.

data is ALWAYS NULL. The runtime keeps a per-signal user-data table but __yo_signal_start never writes to it, so the parameter exists for ABI shape only — do not build on it (issues/stddoc-sys-signal-handler-data-always-null.md). Capture what you need instead, and remember the POSIX rule the wrapper cannot enforce: the body runs in a signal context, so it must stay to async-signal-safe work (set a flag, write to a self-pipe) and must not allocate or take locks.

Functions

on_signal function
fn(sig : Signal, handler : SignalHandler, exn : Exception) -> unit

Register a handler for the given signal.

Parameters

NameTypeNotes
sigSignal
handlerSignalHandler
exnException

Returns: unit

off_signal function
fn(sig : Signal, exn : Exception) -> unit

Remove the handler for the given signal.

Parameters

NameTypeNotes
sigSignal
exnException

Returns: unit