{"record":{"id":"aa9bba9941d9a2ff","repo":"sigoden/aichat","slug":"failed-to-install-ctrl-c-signal-handler","errorCode":null,"errorMessage":"Failed to install CTRL+C signal handler","messagePattern":"Failed to install CTRL\\+C signal handler","errorType":"panic","errorClass":"Panic","httpStatus":null,"severity":"error","filePath":"src/serve.rs","lineNumber":629,"sourceCode":"struct RerankReqBody {\n    documents: Vec<String>,\n    query: String,\n    model: String,\n    top_n: Option<usize>,\n}\n\n#[derive(Debug)]\nenum ResEvent {\n    First(Option<String>),\n    Text(String),\n    ToolCalls(Vec<ToolCall>),\n    Done,\n}\n\nasync fn shutdown_signal() {\n    tokio::signal::ctrl_c()\n        .await\n        .expect(\"Failed to install CTRL+C signal handler\")\n}\n\nfn generate_completion_id() -> String {\n    let random_id = chrono::Utc::now().nanosecond();\n    format!(\"chatcmpl-{random_id}\")\n}\n\nfn set_cors_header(res: &mut AppResponse) {\n    res.headers_mut().insert(\n        hyper::header::ACCESS_CONTROL_ALLOW_ORIGIN,\n        hyper::header::HeaderValue::from_static(\"*\"),\n    );\n    res.headers_mut().insert(\n        hyper::header::ACCESS_CONTROL_ALLOW_METHODS,\n        hyper::header::HeaderValue::from_static(\"GET,POST,PUT,PATCH,DELETE\"),\n    );\n    res.headers_mut().insert(\n        hyper::header::ACCESS_CONTROL_ALLOW_HEADERS,","sourceCodeStart":611,"sourceCodeEnd":647,"githubUrl":"https://github.com/sigoden/aichat/blob/82976d349ad97ac9aae0655ad631dace5e2a6385/src/serve.rs#L611-L647","documentation":"The server's graceful-shutdown helper calls tokio::signal::ctrl_c() and unwraps with this message; the OS refused to install the SIGINT handler. tokio returns an error here only when the signal cannot be registered with the runtime/OS — essentially never in normal operation.","triggerScenarios":"Running outside a tokio runtime context where the signal driver is unavailable; operating systems or sandboxes that block SIGINT registration (some restricted containers, exotic platforms); tokio runtime built without the \"signal\" feature.","commonSituations":"Embedding the serve binary inside another runtime or test harness without enabling tokio's signal feature; minimal container images with restricted seccomp profiles; custom tokio runtime configurations.","solutions":["Enable the tokio \"signal\" feature in Cargo.toml (tokio = { version = \"1\", features = [\"signal\", \"full\"] }).","Run the server inside a normal #[tokio::main] runtime so the signal driver is available.","If the platform cannot register SIGINT, replace the .expect with graceful degradation: log and fall back to terminating without a handler."],"exampleFix":"// before\nasync fn shutdown_signal() {\n    tokio::signal::ctrl_c().await.expect(\"Failed to install CTRL+C signal handler\")\n}\n// after\nasync fn shutdown_signal() {\n    if tokio::signal::ctrl_c().await.is_err() {\n        eprintln!(\"SIGINT handler unavailable; press Ctrl+C to kill\");\n        std::future::pending::<()>().await;\n    }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match tokio::signal::ctrl_c().await {\n    Ok(()) => tracing::info!(\"shutting down on SIGINT\"),\n    Err(e) => tracing::warn!(\"ctrl_c handler unavailable: {e}\"),\n}","preventionTips":["Enable tokio's \"signal\" feature and run inside a standard tokio runtime","Never unwrap signal installation in code that may run on restricted platforms","Test the binary in your actual container/seccomp environment"],"tags":["signal-handling","tokio","runtime"],"backgroundTag":"signal-handler-install-failed","analyzedSha":"82976d349ad97ac9aae0655ad631dace5e2a6385","analyzedAt":"2026-09-09T18:33:06.139Z","contentChangedAt":"2026-09-09T18:33:06.139Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}