{"record":{"id":"0c2d39b4342e6b81","repo":"cloudflare/pingora","slug":"failed-to-register-sigusr1-listener","errorCode":null,"errorMessage":"failed to register SIGUSR1 listener","messagePattern":"failed to register SIGUSR1 listener","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"pingora-core/src/server/daemon.rs","lineNumber":280,"sourceCode":"///\n/// Uses a local tokio runtime with [`tokio::signal::unix`] to listen for `SIGUSR1` instead of\n/// raw signal handlers and polling loops. The daemon's PID is checked periodically via the pid\n/// file — if the process exits before signaling, the parent aborts.\n///\n/// Exits the process directly:\n/// - exit code 0 if `SIGUSR1` is received (daemon is ready).\n/// - exit code 1 if `timeout` elapses (daemon took too long).\n/// - exit code 1 if the pid file exists and the process is no longer running.\nfn wait_for_ready_or_exit(pid_file: &str, timeout: Duration) {\n    let rt = build_parent_runtime();\n    let pid_file = pid_file.to_owned();\n\n    rt.block_on(async move {\n        use tokio::signal::unix::{signal, SignalKind};\n        use tokio::time::{interval, timeout as tokio_timeout};\n\n        let mut sigusr1 =\n            signal(SignalKind::user_defined1()).expect(\"failed to register SIGUSR1 listener\");\n\n        let mut liveness_check = interval(LIVENESS_CHECK_INTERVAL);\n        let mut daemon_pid: Option<libc::pid_t> = None;\n\n        let result = tokio_timeout(timeout, async {\n            loop {\n                tokio::select! {\n                    _ = sigusr1.recv() => {\n                        info!(\"Daemon signaled readiness, parent exiting\");\n                        return;\n                    }\n                    _ = liveness_check.tick() => {\n                        if daemon_pid.is_none() {\n                            daemon_pid = try_read_pid_file(&pid_file);\n                        }\n                        if let Some(pid) = daemon_pid {\n                            if !process_is_running(pid) {\n                                error!(","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/cloudflare/pingora/blob/0046038bd402bc82912da862dadf9a479f31e9f1/pingora-core/src/server/daemon.rs#L262-L298","documentation":"In the daemonization parent, pingora registers a SIGUSR1 listener via tokio::signal::unix::signal(SignalKind::user_defined1()) to learn when the daemonized grandchild is ready. signal() returns Err when the signal cannot be registered — sandbox/syscall restrictions, incompatible signal state, or exhausted signal-listener capacity — and this expect turns that into an immediate panic, aborting the parent during daemonization.","triggerScenarios":"Running the daemonize path (wait_for_ready_or_exit) where tokio's SIGUSR1 registration fails: a container/seccomp sandbox blocking sigaction, an embedding host with conflicting SIGUSR1 handlers or masked signals, or a runtime environment without Unix signal support.","commonSituations":"Daemonizing inside Docker/gVisor/WASI-like sandboxes; pingora embedded in another process that installed its own SIGUSR1 handler or broke signal state; minimal containers with unusual signal semantics.","solutions":["Run the service foreground (skip daemon mode) under systemd/supervisord, which handles readiness and signals for you","Adjust the container/sandbox security policy so sigaction for SIGUSR1 is permitted","Audit the embedding process for other SIGUSR1 users (libraries, custom handlers) and reconfigure them","If a plain unprivileged daemonized run reproduces it, report to pingora — this expect could be a graceful error instead"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Probe SIGUSR1 registration before choosing daemon mode\nfn sigusr1_available() -> bool {\n    tokio::runtime::Builder::new_current_thread()\n        .enable_all()\n        .build()\n        .map(|rt| rt.block_on(async {\n            tokio::signal::unix::signal(\n                tokio::signal::unix::SignalKind::user_defined1(),\n            )\n            .is_ok()\n        }))\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run foreground under an init system instead of pingora daemon mode where possible","Verify the container security profile permits sigaction for SIGUSR1","Never install your own SIGUSR1 handlers in the same process as pingora daemonization"],"tags":["rust","pingora","daemon","signals","sigusr1","tokio","containers","panic"],"backgroundTag":"signal-handler-registration-failed","analyzedSha":"0046038bd402bc82912da862dadf9a479f31e9f1","analyzedAt":"2026-08-16T21:33:22.341Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}