{"record":{"id":"69a02223924f66e5","repo":"xai-org/grok-build","slug":"process-termination-is-only-supported-on-linux-and","errorCode":null,"errorMessage":"process termination is only supported on Linux and Windows","messagePattern":"process termination is only supported on Linux and Windows","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-workspace-daemon/src/daemonize.rs","lineNumber":567,"sourceCode":"    fn drop(&mut self) {\n        use windows::Win32::Foundation::CloseHandle;\n        // SAFETY: the handle is owned by self and closed exactly once.\n        let _ = unsafe { CloseHandle(self.handle) };\n    }\n}\n\n#[cfg(not(any(target_os = \"linux\", windows)))]\nstruct PredecessorTarget;\n\n#[cfg(not(any(target_os = \"linux\", windows)))]\nimpl PredecessorTarget {\n    /// Unsupported platform: never identify a predecessor (the takeover declines rather than kill blind).\n    fn open(_pid: u32, _fragment: &str) -> Option<Self> {\n        None\n    }\n\n    fn signal(&self, _forceful: bool) -> io::Result<()> {\n        Err(io::Error::new(\n            io::ErrorKind::Unsupported,\n            \"process termination is only supported on Linux and Windows\",\n        ))\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    // Used only by the linux-gated predecessor-takeover tests below.\n    #[cfg(target_os = \"linux\")]\n    use std::process::{Child, Command, Stdio};\n\n    use tempfile::TempDir;\n\n    use super::*;\n\n    #[test]\n    fn pidfile_acquire_is_exclusive() {","sourceCodeStart":549,"sourceCodeEnd":585,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-workspace-daemon/src/daemonize.rs#L549-L585","documentation":"The daemon takeover mechanism uses a platform-specific handle to terminate a predecessor daemon process. Process-kill support is implemented only for Linux and Windows; on other platforms Predecessor::open returns None (takeover declines) but if a handle is still used, signal() always fails with io::ErrorKind::Unsupported saying 'process termination is only supported on Linux and Windows'.","triggerScenarios":"Calling signal() (forceful or graceful) on the predecessor-process handle on a platform other than Linux or Windows — e.g. macOS with a stubbed handle, or other Unix flavors where the kill implementation is absent.","commonSituations":"Running the workspace daemon on macOS or a non-Linux Unix where the SIGTERM/SIGKILL path was not ported; porting the daemon to a new platform without implementing the kill handle.","solutions":["Run the daemon takeover/kill path only on Linux or Windows.","Add a cfg(any(target_os=\"linux\", windows)) gate so the kill path is never invoked elsewhere.","On unsupported platforms, decline takeover gracefully (treat like Predecessor::open returning None) instead of calling signal()."],"exampleFix":"// before\npredecessor.signal(true)?;\n// after\n#[cfg(any(target_os = \"linux\", windows))]\npredecessor.signal(true)?;\n#[cfg(not(any(target_os = \"linux\", windows)))]\nreturn Ok(()); // decline takeover rather than kill","handlingStrategy":"fallback","validationCode":"fn kill_supported() -> bool {\n    cfg!(any(target_os = \"linux\", windows))\n}\n// skip predecessor-kill flow when false","typeGuard":null,"tryCatchPattern":"match predecessor.signal(forceful) {\n    Ok(()) => {}\n    Err(e) if e.kind() == std::io::ErrorKind::Unsupported => {\n        // decline takeover instead of failing\n        return decline_takeover();\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Only implement/run takeover on Linux and Windows","Mirror the library's cfg gates in your daemon supervisor","Treat Unsupported as 'cannot take over', not a fatal error"],"tags":["platform","process","signal","unsupported"],"backgroundTag":"unsupported-platform","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}