Skip to main content

Module signal

Module signal 

Source
Expand description

Signal handling — SIGINT / SIGTERM set a graceful-shutdown flag that long-running operations (push / pull / clone / log) poll at natural checkpoints, so a Ctrl-C aborts cleanly with exit::TEMPFAIL (75) rather than leaving a half-finished transfer.

§SIGPIPE is intentionally not registered here

Rust’s runtime sets SIGPIPE to SIG_IGN at process start since 1.65, which means write(2) on a closed pipe returns EPIPE instead of terminating the process. The CLI uses let _ = writeln!(stdout, …) everywhere, so the EPIPE propagates as a silently-dropped io::Error and the program exits at its next natural completion point — exactly the pipeline-friendly behaviour docs/CLI.md advertises.

Registering a signal-hook handler over the runtime’s SIG_IGN would replace a clean kernel-level ignore with a userspace handler that does an atomic store and returns — observationally equivalent but strictly worse (extra wakeups, a window where a different thread might briefly observe a flipped flag we never consume). The integration test in tests/sigpipe.rs is the regression guard: it pipes mkit cat <large-blob> through head -1 and asserts the left-hand exit code is 0. If anyone ever opts mkit out of Rust’s default with #[unix_sigpipe], that test goes red.

§Implementation

signal-hook’s flag module installs the handlers via sigaction(2) and exposes a fully safe API (atomic-bool stores are async-signal-safe; the unsafe lives inside the crate). The CLI stays under its crate-level #![deny(unsafe_code)].

Functions§

install
Install SIGINT/SIGTERM handlers that flip the shared shutdown flag. Idempotent on the signal-hook side: re-registering the same signal layers another handler on top, but the cost is a few bytes and the observable behaviour is unchanged, so callers can invoke this more than once without harm.
interrupted
Alias kept for historical callers. Prefer is_shutdown.
is_shutdown
Returns true once a shutdown was requested via signal. Long- running poll loops should call this at natural checkpoints and return exit::TEMPFAIL when it flips.