astrid-runtime/astrid · error
WinFsp control endpoint remained live after stop
Error message
WinFsp control endpoint remained live after stop
What it means
After the stop handshake, stop_daemon polls the control endpoint path every 25 ms until the daemon stops listening, bounded by DAEMON_STOP_TIMEOUT. If the endpoint is still present when the deadline passes, the daemon never actually released its control socket, so teardown did not complete and the library reports it rather than returning success with a still-live daemon.
Source
Thrown at crates/astrid-storage-provider-winfsp/src/win.rs:675
stream
.read_exact(&mut acknowledgement)
.await
.context("read WinFsp stop acknowledgement")?;
if acknowledgement[0] != b'S' {
bail!("WinFsp daemon returned an invalid stop acknowledgement");
}
Result::<()>::Ok(())
};
tokio::time::timeout(DAEMON_STOP_TIMEOUT, stop)
.await
.map_err(|_| anyhow::anyhow!("WinFsp stop timed out"))??;
let deadline = tokio::time::Instant::now()
.checked_add(DAEMON_STOP_TIMEOUT)
.ok_or_else(|| anyhow::anyhow!("WinFsp stop deadline overflow"))?;
while endpoint_is_present(control_path) {
if tokio::time::Instant::now() >= deadline {
bail!("WinFsp control endpoint remained live after stop");
}
tokio::time::sleep(Duration::from_millis(25)).await;
}
Ok(())
}
fn initialize_winfsp() -> Result<()> {
load_adjacent_winfsp().context("load co-installed WinFsp runtime")?;
winfsp_wrs::init().context("initialize installed WinFsp runtime")
}
fn load_adjacent_winfsp() -> Result<()> {
let Some(directory) = std::env::current_exe()
.ok()
.and_then(|path| path.parent().map(Path::to_path_buf))
else {
return Ok(());
};View on GitHub (pinned to affd8760f4)
Solutions
- Close all applications holding open handles on the WinFsp-mounted volume, then retry stop_daemon.
- Check for orphaned daemon processes from previous runs (taskkill/Stop-Process) and remove stale control endpoint files.
- Increase DAEMON_STOP_TIMEOUT if the workload legitimately takes longer than the current bound to drain.
- If the daemon is consistently wedged, capture its logs/crash dump and file/fix the hang before teardown.
Example fix
// before: stopping while apps still hold the volume open wedges the endpoint app.write_file_on_mount(); provider.stop_daemon().await?; // after: release handles, then stop drop(app); // closes all handles on the mounted volume provider.stop_daemon().await?;
Defensive patterns
Strategy: try-catch
Validate before calling
// Before stopping, check no other handles exist on the mount (best-effort, Windows) // Close application handles and confirm the control endpoint exists: let endpoint_live = endpoint_is_present(control_path); // if true, daemon still running and reachable
Try / catch
match provider.stop_daemon().await {
Ok(()) => {},
Err(e) if e.to_string().contains("remained live after stop") => {
close_all_volume_handles();
tokio::time::sleep(Duration::from_secs(1)).await;
if endpoint_is_present(control_path) { force_terminate_daemon(); }
}
Err(e) => return Err(e),
} Prevention
- Drop all handles on the mounted volume before calling stop_daemon.
- Detect and clean orphaned daemon processes from crashed prior runs.
- Size DAEMON_STOP_TIMEOUT to the workload's realistic drain time.
- Alert on repeated stop failures — usually a hung FSP loop or AV interference.
When it happens
Trigger: Calling stop_daemon when the daemon process accepted the stop request but never exited — e.g. it is wedged in a blocking I/O loop, still holds open handles to mounted files, or the OS has not reaped the listening endpoint before DAEMON_STOP_TIMEOUT elapses.
Common situations: Open file handles from applications using the mounted filesystem prevent daemon exit; a hung FSP loop or antivirus scanning mounted files stalls shutdown; a second orphaned daemon from a previous crashed run owns the endpoint path, so the endpoint never disappears.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
- WinFsp stop timed out
- WinFsp mountpoint did not become ready within {} seconds: {}
- WinFsp daemon returned an invalid stop acknowledgement
- WinFsp stop deadline overflow
- the WinFsp provider is available only on Windows
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/051dad964730cdf4.
Report an issue: GitHub.