{"record":{"id":"4b36ef072a34e253","repo":"astrid-runtime/astrid","slug":"winfsp-service-parent-process-is-not-alive","errorCode":null,"errorMessage":"WinFsp service parent process is not alive","messagePattern":"WinFsp service parent process is not alive","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-storage-provider-winfsp/src/win.rs","lineNumber":197,"sourceCode":"        &launch.lease.callback_path,\n    )\n    .map_err(anyhow::Error::msg)?;\n    let runtime = Arc::new(\n        tokio::runtime::Builder::new_multi_thread()\n            .enable_all()\n            .build()\n            .context(\"start WinFsp service runtime\")?,\n    );\n    runtime.block_on(run_private_service(launch, challenge, runtime.clone()))\n}\n\nasync fn run_private_service(\n    launch: StorageProviderServiceLaunchV1,\n    challenge: String,\n    runtime: Arc<tokio::runtime::Runtime>,\n) -> Result<()> {\n    if !parent_is_alive(&launch.parent) {\n        bail!(\"WinFsp service parent process is not alive\");\n    }\n    probe_callback(&launch).await?;\n    let listener = local_transport::bind(&launch.control_path).with_context(|| {\n        format!(\n            \"bind WinFsp service control {}\",\n            launch.control_path.display()\n        )\n    })?;\n    let callback = CallbackFs::new(launch.lease.clone(), runtime)\n        .map_err(|failure| anyhow::anyhow!(\"build WinFsp callback filesystem: {failure:?}\"))?;\n    initialize_winfsp()?;\n    let mountpoint = U16CString::from_os_str(launch.mountpoint.as_os_str())\n        .map_err(|_| anyhow::anyhow!(\"WinFsp mountpoint is not valid UTF-16\"))?;\n    let filesystem = FileSystem::start(\n        volume_params(launch.lease.access),\n        Some(&mountpoint),\n        callback,\n    )","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage-provider-winfsp/src/win.rs#L179-L215","documentation":"run_private_service starts by checking the parent process recorded in the launch (launch.parent) via parent_is_alive. If the parent has exited, the service bails: continuing would leave an orphaned privileged process with no one to own the control channel or reap the result. The check is a liveness handshake between parent and child.","triggerScenarios":"The parent process crashes or exits between writing the launch document and the service reading it; the launch embeds a stale parent PID/token from a previous run; the wrong PID was serialized into launch.parent.","commonSituations":"Parent killed by a timeout runner or Ctrl+C during startup; services launched by a short-lived bootstrap script that exits immediately; PID reuse pointing at a different (dead) process; relaunching a stale launch file.","solutions":["Ensure the parent stays alive for the whole child startup handshake (wait for the ready challenge before exiting)","Log and retry the launch if the parent was terminated, regenerating the launch document with a fresh live PID","Verify parent_is_alive's inputs: the PID/token in the launch must refer to the actual launching process","If the parent intentionally spawns and exits, restructure to keep a supervisor process alive instead"],"exampleFix":"// before\nspawn_service(&launch)?;\nstd::process::exit(0); // parent gone before child validates liveness\n// after\nspawn_service(&launch)?;\nwait_for_service_ready(&launch); // parent stays alive through the handshake","handlingStrategy":"try-catch","validationCode":"// parent side: confirm your own process is alive and the PID recorded is current\nassert_eq!(launch.parent.pid, std::process::id(), \"launch must record the live parent PID\");","typeGuard":"fn launch_parent_is_self(launch: &StorageProviderServiceLaunchV1) -> bool {\n    launch.parent.pid == std::process::id()\n}","tryCatchPattern":"match service_err {\n    Err(e) if e.to_string().contains(\"parent process is not alive\") => {\n        eprintln!(\"parent exited during handshake; relaunch with a live supervisor\");\n        relaunch_with_supervisor()?;\n    }\n    other => other?,\n}","preventionTips":["Keep a supervisor process alive through the whole child handshake","Never exit the parent before the service signals readiness","Regenerate launch documents per run; never reuse stale ones","Log parent PID at spawn to catch PID-reuse confusion"],"tags":["windows","winfsp","process","ipc"],"backgroundTag":"parent-process-not-alive","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}