{"record":{"id":"791304f3bde5b1d4","repo":"libnyanpasu/clash-nyanpasu","slug":"failed-to-send-initd-signal-e","errorCode":null,"errorMessage":"Failed to send initd signal: {e}","messagePattern":"Failed to send initd signal: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"backend/tauri/src/shutdown_hook.rs","lineNumber":172,"sourceCode":"            0,\n            std::ptr::null_mut(),\n            std::ptr::null_mut(),\n            h_instance,\n            std::ptr::null_mut(),\n        )\n    };\n    if hidden_window.is_null() {\n        let err = Error::from_win32();\n        anyhow::bail!(\"Failed to create hidden window: {err}\");\n    }\n\n    let window_handle = WindowHandle {\n        hwnd: hidden_window,\n        h_instance,\n    };\n\n    if let Err(e) = initd_tx.send(()) {\n        anyhow::bail!(\"Failed to send initd signal: {e}\");\n    }\n\n    let mut msg = unsafe { std::mem::zeroed::<MSG>() };\n    unsafe {\n        loop {\n            let result = GetMessageW(&mut msg, window_handle.hwnd, 0, 0);\n            if result > 0 {\n                TranslateMessage(&msg);\n                DispatchMessageW(&msg);\n            } else {\n                let err = Error::from_win32();\n                tracing::error!(\n                    \"GetMessageW failed with {result}, shutdown hook thread exiting: {err}\"\n                );\n                break;\n            }\n        }\n    }","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri/src/shutdown_hook.rs#L154-L190","documentation":"The oneshot initd_tx channel used to signal that the shutdown-hook window finished initializing rejected the send, meaning the receiver was already dropped (e.g. the awaiting thread errored, panicked, or the setup future was cancelled).","triggerScenarios":"Calling setup_shutdown_hook when the receiving side of initd_tx has been dropped before send(()) succeeds — the spawn wrapper cancelled, or the waiter thread exited early on another error.","commonSituations":"Startup races where the bootstrap task is torn down while the hook thread is still initializing, or a panic in the code awaiting the init signal.","solutions":["Check whether the receiver future/thread exited early and fix the underlying error it reported first.","Treat a dropped receiver as cancellation: log and return cleanly instead of propagating as fatal, since the hook is already set up structurally.","Ensure the waiter is spawned/awaited before the window thread runs, or use a tolerant send (ignore SendError).","Add logging on the receive side to detect premature teardown."],"exampleFix":"// before\nif let Err(e) = initd_tx.send(()) {\n    anyhow::bail!(\"Failed to send initd signal: {e}\");\n}\n// after\nif let Err(e) = initd_tx.send(()) {\n    log::debug!(\"initd receiver dropped, hook teardown in progress: {e}\");\n}","handlingStrategy":"try-catch","validationCode":"// keep receiver alive until send completes\nlet (initd_tx, initd_rx) = tokio::sync::oneshot::channel::<()>();\nassert!(!initd_rx.is_terminated(), \"receiver already dropped\");","typeGuard":null,"tryCatchPattern":"if let Err(e) = initd_tx.send(()) {\n    // SendError only occurs when receiver dropped: treat as cancellation\n    log::debug!(\"init signal receiver gone: {}\", e);\n}","preventionTips":["Spawn the receiver future before starting the window thread that sends initd","Never bail out of the waiter on unrelated errors before receiving the signal","Use a tolerant (non-failing) send for one-shot init notifications"],"tags":["windows","channel","oneshot","race-condition"],"backgroundTag":"broken-pipe","analyzedSha":"f7dbce2997c633e484f54788035e770b3ee99773","analyzedAt":"2026-09-08T01:24:59.197Z","contentChangedAt":"2026-09-08T01:24:59.197Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}