From c0c52a5f8c03a394b1a9d99a4e3830383bb01887 Mon Sep 17 00:00:00 2001 From: robcholz <84130577+robcholz@users.noreply.github.com> Date: Sat, 7 Feb 2026 17:00:39 -0500 Subject: [PATCH] =?UTF-8?q?fix:=20=20avoids=20the=20=E2=80=9CPID=20reused?= =?UTF-8?q?=E2=80=9D=20false=20positive=20while=20still=20honoring=20a=20r?= =?UTF-8?q?eal=20running=20manager?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/vm_manager.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/vm_manager.rs b/src/vm_manager.rs index b6f5fb3..c60ebb1 100644 --- a/src/vm_manager.rs +++ b/src/vm_manager.rs @@ -2,6 +2,7 @@ use std::{ env, fs, io::{Read, Write}, os::unix::{ + fs::FileTypeExt, fs::PermissionsExt, io::AsRawFd, net::{UnixListener, UnixStream}, @@ -167,10 +168,18 @@ fn spawn_manager_process( fn ensure_pid_file(project_root: &Path) -> Result> { let instance_dir = ensure_instance_dir(project_root)?; let pid_path = instance_dir.join(VM_MANAGER_PID_NAME); + let socket_path = instance_dir.join(VM_MANAGER_SOCKET_NAME); if let Ok(content) = fs::read_to_string(&pid_path) { if let Ok(pid) = content.trim().parse::() { if pid_is_alive(pid) { - return Err(format!("vm manager already running (pid {pid})").into()); + if is_socket_path(&socket_path) { + return Err(format!("vm manager already running (pid {pid})").into()); + } + tracing::warn!( + pid, + path = %socket_path.display(), + "stale pid file detected with missing socket" + ); } } let _ = fs::remove_file(&pid_path); @@ -192,6 +201,12 @@ fn cleanup_stale_manager(instance_dir: &Path) { let _ = fs::remove_file(&pid_path); } +fn is_socket_path(path: &Path) -> bool { + fs::metadata(path) + .map(|meta| meta.file_type().is_socket()) + .unwrap_or(false) +} + struct PidFileGuard { path: PathBuf, }