std::signal
std::signal provides a small, pollable signal-watching surface intended for
terminal/TUI programs.
On hosted Linux targets, this module is backed by signalfd(2), which exposes
pending signals as a readable file descriptor. This integrates naturally with:
std::runtime::event_loop::{fd_wait_readable2, fd_wait_readable_any, ...}std::sync::ChannelBorrow(T).wait_fd()std::abort_controller::AbortSignalBorrow.wait_fd()
signalfd(2) integration#
The main type is SignalFD:
SignalFD.open(signo)blockssignoin the calling thread, then returns aSignalFDwhose.wait_fd()becomes readable when the signal is pending for the process.SignalFD.read_signo()reads one pending signal number from the fd.
Important: thread signal masks#
Signal masks are per-thread.
To reliably route a signal to a signalfd(2) across a multi-threaded program,
ensure the relevant signals are blocked in all threads that might otherwise
receive them.
In practice:
- call
SignalFD.open(...)early in your program (before spawningtask fnthreads), and - keep the returned
SignalFDalive for as long as you want to observe the signal.
Newly-created threads inherit the parent thread’s signal mask, so blocking signals early keeps delivery consistent.
Example: SIGWINCH resize notifications#
This pattern avoids polling terminal size in a loop:
import std::io;
import std::runtime::event_loop;
import std::runtime::io;
import std::runtime::mem;
import std::signal;
async fn main () -> int {
let sfd_r: std::signal::SignalFDResult = std::signal::SignalFD.open(std::signal::SIGWINCH);
if sfd_r.is_err() {
return 1;
}
let sfd: std::signal::SignalFD = std::signal::SignalFDResult.ok_value(sfd_r) ?? std::signal::SignalFD{};
// Wait until a resize signal is pending.
let fds_mem: u64 = std::runtime::mem::alloc(8);
if fds_mem == 0 { return 2; }
std::runtime::mem::store_u64(fds_mem, 0, sfd.wait_fd() as u64);
let which: i64 = await std::runtime::event_loop::fd_wait_readable_any(fds_mem, 1);
std::runtime::mem::free(fds_mem);
if which != 0 { return 3; }
let signo_r: std::signal::SignalReadResult = sfd.read_signo();
if signo_r.is_err() {
return 4;
}
// Now re-query terminal size and redraw.
let _signo: int = std::signal::SignalReadResult.ok_value(signo_r) ?? 0;
let _size: std::io::TTYSize? = std::io::tty_size(std::runtime::io::STDIN_FD);
return 0;
}
Portability#
Today:
- hosted Linux targets: supported (
signalfd(2)). - other targets:
SignalFD.open*returns anIOFailederror.
As more platforms are implemented, this module will extend to cover portable signal waiting where possible.
Source repository · Edit this page · View Markdown