mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-20 00:02:19 +00:00
fix(daemon): find and stop orphaned daemons on macOS when PID file is missing
This commit is contained in:
parent
80c9364c4c
commit
37247587c4
1 changed files with 54 additions and 17 deletions
|
|
@ -349,25 +349,26 @@ pub fn start(cli: &CliConfig, host: &str, port: u16, token: Option<&str>) -> Res
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Find the PID of a process listening on the given port using lsof.
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub fn stop(host: &str, port: u16) -> Result<(), CliError> {
|
fn find_process_on_port(port: u16) -> Option<u32> {
|
||||||
let pid_path = daemon_pid_path(host, port);
|
let output = std::process::Command::new("lsof")
|
||||||
|
.args(["-i", &format!(":{port}"), "-t", "-sTCP:LISTEN"])
|
||||||
|
.output()
|
||||||
|
.ok()?;
|
||||||
|
|
||||||
let pid = match read_pid(&pid_path) {
|
if !output.status.success() {
|
||||||
Some(pid) => pid,
|
return None;
|
||||||
None => {
|
|
||||||
eprintln!("daemon is not running (no PID file)");
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if !is_process_running(pid) {
|
|
||||||
eprintln!("daemon is not running (stale PID file)");
|
|
||||||
let _ = remove_pid(&pid_path);
|
|
||||||
let _ = remove_version_file(host, port);
|
|
||||||
return Ok(());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||||
|
// lsof -t returns just the PID(s), one per line
|
||||||
|
stdout.lines().next()?.trim().parse::<u32>().ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Stop a process by PID with SIGTERM then SIGKILL if needed.
|
||||||
|
#[cfg(unix)]
|
||||||
|
fn stop_process(pid: u32, host: &str, port: u16, pid_path: &Path) -> Result<(), CliError> {
|
||||||
eprintln!("stopping daemon (PID {pid})...");
|
eprintln!("stopping daemon (PID {pid})...");
|
||||||
|
|
||||||
// SIGTERM
|
// SIGTERM
|
||||||
|
|
@ -379,7 +380,7 @@ pub fn stop(host: &str, port: u16) -> Result<(), CliError> {
|
||||||
for _ in 0..50 {
|
for _ in 0..50 {
|
||||||
std::thread::sleep(Duration::from_millis(100));
|
std::thread::sleep(Duration::from_millis(100));
|
||||||
if !is_process_running(pid) {
|
if !is_process_running(pid) {
|
||||||
let _ = remove_pid(&pid_path);
|
let _ = remove_pid(pid_path);
|
||||||
let _ = remove_version_file(host, port);
|
let _ = remove_version_file(host, port);
|
||||||
eprintln!("daemon stopped");
|
eprintln!("daemon stopped");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
@ -392,12 +393,48 @@ pub fn stop(host: &str, port: u16) -> Result<(), CliError> {
|
||||||
libc::kill(pid as i32, libc::SIGKILL);
|
libc::kill(pid as i32, libc::SIGKILL);
|
||||||
}
|
}
|
||||||
std::thread::sleep(Duration::from_millis(100));
|
std::thread::sleep(Duration::from_millis(100));
|
||||||
let _ = remove_pid(&pid_path);
|
let _ = remove_pid(pid_path);
|
||||||
let _ = remove_version_file(host, port);
|
let _ = remove_version_file(host, port);
|
||||||
eprintln!("daemon killed");
|
eprintln!("daemon killed");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
pub fn stop(host: &str, port: u16) -> Result<(), CliError> {
|
||||||
|
let base_url = format!("http://{host}:{port}");
|
||||||
|
let pid_path = daemon_pid_path(host, port);
|
||||||
|
|
||||||
|
let pid = match read_pid(&pid_path) {
|
||||||
|
Some(pid) => pid,
|
||||||
|
None => {
|
||||||
|
// No PID file - but check if daemon is actually running via health check
|
||||||
|
// This can happen if PID file was deleted but daemon is still running
|
||||||
|
if check_health(&base_url, None)? {
|
||||||
|
eprintln!("daemon is running but PID file missing; finding process on port {port}...");
|
||||||
|
if let Some(pid) = find_process_on_port(port) {
|
||||||
|
eprintln!("found daemon process {pid}");
|
||||||
|
return stop_process(pid, host, port, &pid_path);
|
||||||
|
} else {
|
||||||
|
return Err(CliError::Server(format!(
|
||||||
|
"daemon is running on port {port} but cannot find PID"
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eprintln!("daemon is not running (no PID file)");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if !is_process_running(pid) {
|
||||||
|
eprintln!("daemon is not running (stale PID file)");
|
||||||
|
let _ = remove_pid(&pid_path);
|
||||||
|
let _ = remove_version_file(host, port);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_process(pid, host, port, &pid_path)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub fn stop(host: &str, port: u16) -> Result<(), CliError> {
|
pub fn stop(host: &str, port: u16) -> Result<(), CliError> {
|
||||||
let pid_path = daemon_pid_path(host, port);
|
let pid_path = daemon_pid_path(host, port);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue