atuinsh/atuin · error
failed to register signal handler
Error message
failed to register signal handler
What it means
`shutdown_signal` on Unix registers a SIGTERM handler with tokio and panics via `.expect("failed to register signal handler")` if registration fails. tokio's signal registration fails when the OS refuses the handler installation — typically when not running on a real OS thread setup that supports signals, when the process has no permission for the signal, or when signal dispositions are externally controlled.
Solutions
- Check the container/sandbox security profile allows sigaction for SIGTERM/SIGINT
- Ensure the server runs on a proper multi-thread tokio runtime
- Replace expect with graceful degradation: log a warning and fall back to waiting on ctrl_c or indefinitely
Example fix
// before
let mut term = signal::unix::signal(signal::unix::SignalKind::terminate())
.expect("failed to register signal handler");
// after
let mut term = signal::unix::signal(signal::unix::SignalKind::terminate())
.unwrap_or_else(|e| {
eprintln!("failed to register SIGTERM handler: {e}; skipping graceful shutdown on SIGTERM");
signal::unix::signal(signal::unix::SignalKind::hangup()).expect("failed to register signal handler")
}); Defensive patterns
Strategy: try-catch
Validate before calling
// check before serving (unix) let term_ok = signal::unix::signal(signal::unix::SignalKind::terminate()).is_ok();
Try / catch
match signal::unix::signal(signal::unix::SignalKind::terminate()) {
Ok(mut s) => { /* proceed with shutdown select */ }
Err(e) => eprintln!("SIGTERM handler unavailable: {e}"),
} Prevention
- Run the server with a standard tokio multi_thread runtime
- Relax seccomp/sandbox profiles to allow sigaction for SIGTERM/SIGINT
- Test server startup inside your actual container/sandbox image
When it happens
Trigger: Calling `launch` or `launch_metrics_server` in an environment where `signal::unix::signal(SignalKind::terminate())` returns Err — e.g. running inside restricted containers/seccomp sandboxes that block sigaction, or after tokio runtime misuse.
Common situations: Docker containers with hardened seccomp profiles, restricted CI runners, unusual sandboxing (gVisor), or embedding the server in a non-tokio runtime context.
Related errors
- Atuin running with no parent!
- clone pty reader
- Could not build config
- Could not build default
- Could not deserialize config
AI-assisted analysis of atuinsh/atuin@900007c480 (2026-09-19).
Data as JSON: /api/errors/116a1333087d70df.
Report an issue: GitHub.
Appendix: source
Thrown at crates/atuin-server/src/lib.rs:30
mod handlers;
mod metrics;
mod router;
mod trace;
pub mod db;
pub use settings::{Settings, example_config};
pub mod settings;
use tokio::net::TcpListener;
use tokio::signal;
#[cfg(target_family = "unix")]
async fn shutdown_signal() {
let mut term = signal::unix::signal(signal::unix::SignalKind::terminate())
.expect("failed to register signal handler");
let mut interrupt = signal::unix::signal(signal::unix::SignalKind::interrupt())
.expect("failed to register signal handler");
tokio::select! {
_ = term.recv() => {},
_ = interrupt.recv() => {},
};
eprintln!("Shutting down gracefully...");
}
#[cfg(target_family = "windows")]
async fn shutdown_signal() {
signal::windows::ctrl_c().expect("failed to register signal handler").recv().await;
eprintln!("Shutting down gracefully...");
}
pub async fn launch(settings: Settings, addr: SocketAddr) -> Result<()> {
launch_with_tcp_listener(View on GitHub (pinned to 900007c480)