{"record":{"id":"116a1333087d70df","repo":"atuinsh/atuin","slug":"failed-to-register-signal-handler","errorCode":null,"errorMessage":"failed to register signal handler","messagePattern":"failed to register signal handler","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/atuin-server/src/lib.rs","lineNumber":26,"sourceCode":"use eyre::{Context, Result};\n\nmod handlers;\nmod metrics;\nmod router;\nmod trace;\n\npub use settings::Settings;\npub use settings::example_config;\n\npub mod settings;\n\nuse tokio::net::TcpListener;\nuse tokio::signal;\n\n#[cfg(target_family = \"unix\")]\nasync fn shutdown_signal() {\n    let mut term = signal::unix::signal(signal::unix::SignalKind::terminate())\n        .expect(\"failed to register signal handler\");\n    let mut interrupt = signal::unix::signal(signal::unix::SignalKind::interrupt())\n        .expect(\"failed to register signal handler\");\n\n    tokio::select! {\n        _ = term.recv() => {},\n        _ = interrupt.recv() => {},\n    };\n    eprintln!(\"Shutting down gracefully...\");\n}\n\n#[cfg(target_family = \"windows\")]\nasync fn shutdown_signal() {\n    signal::windows::ctrl_c()\n        .expect(\"failed to register signal handler\")\n        .recv()\n        .await;\n    eprintln!(\"Shutting down gracefully...\");\n}","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/atuinsh/atuin/blob/202f6ad98ee0da165c35cdb2afbc5b13d6ab81a1/crates/atuin-server/src/lib.rs#L8-L44","documentation":"When the sync server boots, atuin_server::launch() spawns shutdown_signal(), which registers a SIGTERM listener via tokio::signal::unix::signal. Registration fails if the current runtime has no IO/signal driver or the OS denies the operation, and the expect panics with 'failed to register signal handler', aborting server startup.","triggerScenarios":"Calling atuin_server::launch/launch_with_tcp_listener from a tokio runtime built without enable_all()/enable_io(); fd or memory exhaustion (EMFILE) while installing the signal machinery; sandboxes blocking sigaction.","commonSituations":"Embedding the sync server (axum host apps, custom binaries) in a runtime lacking the IO driver; resource-starved containers at boot.","solutions":["Run the server through atuin_server::launch as the shipped binary does, inside a fully enabled runtime","Build any hosting runtime with .enable_all() before awaiting launch","Raise LimitNOFILE / memory if boot-time registration fails"],"exampleFix":"// before\nlet rt = tokio::runtime::Builder::new_multi_thread().build()?;\n\n// after — signal registration needs the IO driver\nlet rt = tokio::runtime::Builder::new_multi_thread()\n    .enable_all()\n    .build()?;","handlingStrategy":"validation","validationCode":"let rt = tokio::runtime::Builder::new_multi_thread()\n    .enable_all() // signal registration requires the IO driver\n    .build()?;\nrt.block_on(async { atuin_server::launch::<Db>(settings, addr).await })?;","typeGuard":null,"tryCatchPattern":"match tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate()) {\n    Ok(term) => tokio::select! { _ = term.recv() => {} },\n    Err(e) => {\n        eprintln!(\"sigterm handler unavailable: {e}; relying on SIGINT\");\n        tokio::signal::unix::signal(tokio::signal::unix::SignalKind::interrupt())\n            .expect(\"sigint\")\n            .recv()\n            .await;\n    }\n}","preventionTips":["Run the sync server via launch() inside a runtime built with enable_all()","Do not host atuin_server on executors without an IO driver","Keep boot-time fd headroom so signal setup cannot fail under load"],"tags":["rust","tokio","signals","sigterm","server","panic"],"backgroundTag":"tokio-signal-registration-failed","analyzedSha":"202f6ad98ee0da165c35cdb2afbc5b13d6ab81a1","analyzedAt":"2026-08-16T19:30:24.731Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}