linera-io/linera-protocol · error
Failed to set up SIGTERM handler
Error message
Failed to set up SIGTERM handler
What it means
Panics when tokio::signal::unix::signal(SignalKind::terminate()) cannot install a SIGTERM handler in listen_for_shutdown_signals. The registration itself fails at startup, before any signal is delivered — typically because the tokio runtime lacks the signal/IO driver or the OS refused to install the handler. The panic drops the shutdown guard, so the CancellationToken fires and the node shuts down immediately.
Source
Thrown at linera-base/src/lib.rs:182
}
/// Helper function for allocative.
pub fn visit_allocative_simple<T>(_: &T, visitor: &mut allocative::Visitor<'_>) {
visitor.visit_simple_sized::<T>();
}
/// Listens for shutdown signals, and notifies the [`CancellationToken`] if one is
/// received.
#[cfg(not(target_arch = "wasm32"))]
pub async fn listen_for_shutdown_signals(shutdown_sender: CancellationToken) {
let _shutdown_guard = shutdown_sender.drop_guard();
#[cfg(unix)]
{
let mut sigint =
unix::signal(unix::SignalKind::interrupt()).expect("Failed to set up SIGINT handler");
let mut sigterm =
unix::signal(unix::SignalKind::terminate()).expect("Failed to set up SIGTERM handler");
let mut sighup =
unix::signal(unix::SignalKind::hangup()).expect("Failed to set up SIGHUP handler");
tokio::select! {
_ = sigint.recv() => debug!("Received SIGINT"),
_ = sigterm.recv() => debug!("Received SIGTERM"),
_ = sighup.recv() => debug!("Received SIGHUP"),
}
}
#[cfg(windows)]
{
tokio::signal::ctrl_c()
.await
.expect("Failed to set up Ctrl+C handler");
debug!("Received Ctrl+C");
}
}View on GitHub (pinned to 6c226ddcb3)
Solutions
- Enable the full driver set on the runtime: .enable_all() (or .enable_io() plus the signal feature) before spawning the listener
- Confirm tokio's 'signal' feature is present: cargo tree -e features -i tokio
- Audit the container/sandbox security profile for sigaction restrictions on SIGTERM
- Raise file-descriptor limits if startup also logs EMFILE/ENOBUFS errors
- Treat a panicked listener task as fatal — the shutdown token was already cancelled, so perform a clean exit
Example fix
// before
fn main() {
let rt = tokio::runtime::Builder::new_current_thread().build().unwrap();
rt.block_on(async { /* ... spawn listen_for_shutdown_signals ... */ });
}
// after
fn main() {
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all() // without this, unix::signal(SignalKind::terminate()) fails
.build()
.unwrap();
rt.block_on(async { /* ... */ });
} Defensive patterns
Strategy: validation
Validate before calling
// Signal registration needs the runtime's IO/signal driver:
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()?;
// Only now is listen_for_shutdown_signals safe to spawn for SIGTERM. Try / catch
let handle = tokio::spawn(listen_for_shutdown_signals(token));
if let Err(e) = handle.await {
assert!(!e.is_panic(), "signal listener panicked; token already cancelled — exit now");
} Prevention
- Prefer #[tokio::main] (which enables all drivers) over manual Runtime::new variants
- Keep supervisors (systemd) sending SIGTERM only to the main PID, not to a session with conflicting handlers
- Document in your runbook that a panic here means the process is already shutting down via the token
When it happens
Trigger: Running the node's signal listener on a runtime built without .enable_all(); a sandboxed or restricted environment (seccomp, gVisor, some minimal containers) where sigaction for SIGTERM is denied; resource exhaustion (EMFILE) preventing tokio's global signal registry from being created; tokio compiled without the 'signal' feature.
Common situations: Custom binaries or integration tests that hand-construct a tokio Runtime and call linera-base's run(); deploying validators into hardened container images; CI environments that strip tokio default features via a shared workspace Cargo.toml.
Related errors
- Failed to set up SIGINT handler
- Failed to set up SIGHUP handler
- Failed to set up Ctrl+C handler
- owner should be different from spender
- invalid block export configuration: {message}
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/2cca0f5714be4396.
Report an issue: GitHub.