From 81a2baa5eb1c86d66db691090d8aaf874b7709fa Mon Sep 17 00:00:00 2001 From: Khoa Vo Date: Wed, 1 Jul 2026 11:25:53 +0700 Subject: [PATCH] fix: improve single-instance lock with PID + stale detection --- daemon/src/main.rs | 51 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/daemon/src/main.rs b/daemon/src/main.rs index 2e53036..98f1580 100644 --- a/daemon/src/main.rs +++ b/daemon/src/main.rs @@ -545,16 +545,61 @@ fn recover_display_env() { fn ensure_single_instance(name: &str) { let uid = unsafe { libc::getuid() }; - let path = format!("/tmp/{}-{}.lock", name, uid); - let path_c = std::ffi::CString::new(path).unwrap(); + let path_str = format!("/tmp/{}-{}.lock", name, uid); + let path = std::path::Path::new(&path_str); + let path_c = std::ffi::CString::new(path_str.as_str()).unwrap(); let fd = unsafe { libc::open(path_c.as_ptr(), libc::O_CREAT | libc::O_RDWR, 0o600) }; if fd < 0 { eprintln!("[{}] Failed to open lock file", name); std::process::exit(1); } let res = unsafe { libc::flock(fd, libc::LOCK_EX | libc::LOCK_NB) }; + if res == 0 { + // Write PID to lock file for stale detection + let pid = unsafe { libc::getpid() }; + let _ = std::fs::write(path, format!("{}", pid)); + } if res < 0 { - eprintln!("[{}] Another instance is already running. Exiting.", name); + let err = unsafe { *libc::__errno_location() }; + if err == libc::EAGAIN || err == libc::EWOULDBLOCK { + // Lock contention — check if the lock is stale + if let Ok(pid_str) = std::fs::read_to_string(path) { + if let Ok(pid) = pid_str.trim().parse::() { + let alive = unsafe { libc::kill(pid, 0) } == 0; + if !alive { + eprintln!( + "[{}] Stale lock from PID {}, removing and retrying...", + name, pid + ); + unsafe { libc::close(fd) }; + let _ = std::fs::remove_file(path); + let path_c2 = std::ffi::CString::new(path_str.as_str()).unwrap(); + let fd2 = unsafe { + libc::open(path_c2.as_ptr(), libc::O_CREAT | libc::O_RDWR, 0o600) + }; + if fd2 >= 0 { + let res2 = unsafe { libc::flock(fd2, libc::LOCK_EX | libc::LOCK_NB) }; + if res2 == 0 { + return; + } + unsafe { libc::close(fd2) }; + } + } else { + eprintln!("[{}] Another instance (PID {}) is running. Exiting.", name, pid); + std::process::exit(0); + } + } + } + eprintln!( + "[{}] Another instance is already running (errno={}). Exiting.", + name, err + ); + } else { + eprintln!( + "[{}] Lock error (errno={}). Exiting.", + name, err + ); + } std::process::exit(0); } }