Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/ensure_up.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,23 @@ pub fn pid_is_alive(pid: u32) -> bool {
crate::platform::process_alive(pid)
}

/// Cheap "is THIS session's daemon alive" — reads our own `daemon.pid` and
/// checks that one pid. Unlike [`daemon_liveness`] it does NOT run the
/// machine-wide process-enumeration scan (`find_processes_by_cmdline`) or
/// `list_sessions` (which reads every by-key home's agent-card) or a
/// per-session `pid_is_alive` sweep — work that only the orphan/`wire status`
/// path needs. On Windows those each shell out (PowerShell CIM, `tasklist` ×N,
/// hundreds of NTFS dir reads), so calling full `daemon_liveness` purely to read
/// `pidfile_alive` made every `wire_send` cost seconds (#350). One pidfile read
/// plus one `pid_is_alive` (one `tasklist` on Windows) yields the identical
/// `daemon_seen` boolean for a fraction of the cost.
pub fn daemon_pidfile_alive() -> bool {
read_pid_record("daemon")
.pid()
.map(pid_is_alive)
.unwrap_or(false)
}

/// Read the daemon pid file + pgrep in one shot, producing a snapshot
/// every caller can interpret identically. The point of this helper
/// is that three independent callers used to compute liveness three
Expand Down Expand Up @@ -750,4 +767,14 @@ mod tests {
assert_eq!(daemon_version_mismatch(), None);
});
}

#[test]
fn daemon_pidfile_alive_false_without_pidfile() {
// No daemon.pid → false, with no process-enumeration shell-out. (The
// send-path annotation reads only this, not the full daemon_liveness
// scan — the #350 Windows hot-path fix.)
crate::config::test_support::with_temp_home(|| {
assert!(!daemon_pidfile_alive());
});
}
}
14 changes: 10 additions & 4 deletions src/mcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1362,10 +1362,14 @@ fn tool_send(args: &Value) -> Result<Value, String> {
// these are diagnostic-only (the verdict in `status` is the
// authoritative answer), but they're cheap to compute and
// existing consumers may key on them.
let snap = crate::ensure_up::daemon_liveness();
// Cheap pidfile-only liveness: the annotation needs just `daemon_seen`,
// NOT the machine-wide orphan scan `daemon_liveness` runs (PowerShell
// CIM + list_sessions over every by-key home + tasklist ×N on Windows —
// seconds per send, #350). One pidfile check gives the same boolean.
let daemon_seen = crate::ensure_up::daemon_pidfile_alive();
let last_sync_age = crate::ensure_up::last_sync_age_seconds();
if let Some(obj) = v.as_object_mut() {
obj.insert("daemon_seen".into(), json!(snap.pidfile_alive));
obj.insert("daemon_seen".into(), json!(daemon_seen));
obj.insert("last_sync_age_seconds".into(), json!(last_sync_age));
obj.insert(
"stale_sync".into(),
Expand All @@ -1378,7 +1382,9 @@ fn tool_send(args: &Value) -> Result<Value, String> {
// Legacy --queue path. Outbox-write, daemon push loop drains.
let line = serde_json::to_vec(&signed).map_err(|e| e.to_string())?;
let outbox = config::append_outbox_record(peer, &line).map_err(|e| e.to_string())?;
let snap = crate::ensure_up::daemon_liveness();
// Cheap pidfile-only liveness (see the sync branch above) — avoids the
// machine-wide orphan scan on the hot send path (#350).
let daemon_seen = crate::ensure_up::daemon_pidfile_alive();
let last_sync_age = crate::ensure_up::last_sync_age_seconds();
// Honesty check mirror of the CLI: if the peer is BOTH
// unpinned in trust AND has no pending pair (outbound or
Expand Down Expand Up @@ -1406,7 +1412,7 @@ fn tool_send(args: &Value) -> Result<Value, String> {
"status": "queued",
"peer": peer,
"outbox": outbox.to_string_lossy(),
"daemon_seen": snap.pidfile_alive,
"daemon_seen": daemon_seen,
"last_sync_age_seconds": last_sync_age,
"stale_sync": config::stale_sync(last_sync_age),
});
Expand Down