ipc: check for PID liveness via libc:kill
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I961c138cf8341bad6a27c450706de11d6a6a6964
This commit is contained in:
parent
614d76fd74
commit
62f3230456
1 changed files with 42 additions and 12 deletions
54
src/ipc.rs
54
src/ipc.rs
|
|
@ -53,6 +53,25 @@ impl From<serde_json::Error> for IpcError {
|
|||
}
|
||||
}
|
||||
|
||||
/// Check whether a process with the given PID is still alive.
|
||||
#[cfg(unix)]
|
||||
fn is_process_alive(pid: u32) -> bool {
|
||||
unsafe {
|
||||
if libc::kill(pid as i32, 0) == 0 {
|
||||
return true;
|
||||
}
|
||||
let errno = *libc::__errno_location();
|
||||
// EPERM means the process exists but we can't signal it.
|
||||
errno == libc::EPERM
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn is_process_alive(_pid: u32) -> bool {
|
||||
// Cannot verify on non-Unix; assume alive to stay safe.
|
||||
true
|
||||
}
|
||||
|
||||
/// Represents an ongoing operation tracked in IPC
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct OngoingOperation {
|
||||
|
|
@ -279,7 +298,7 @@ impl IpcCoordinator {
|
|||
let mut operations = self.load_operations()?;
|
||||
log::debug!("Loaded {} existing operations", operations.len());
|
||||
|
||||
// Clean up stale operations (older than 10 minutes)
|
||||
// Clean up stale operations (older than 10 minutes or with dead PIDs)
|
||||
let now = SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.unwrap_or(Duration::ZERO)
|
||||
|
|
@ -289,18 +308,21 @@ impl IpcCoordinator {
|
|||
.iter()
|
||||
.filter(|op| {
|
||||
op.status == OperationStatus::Running
|
||||
&& now.saturating_sub(op.started_at) > 600
|
||||
&& (now.saturating_sub(op.started_at) > 600
|
||||
|| !is_process_alive(op.pid))
|
||||
})
|
||||
.count();
|
||||
|
||||
operations.retain(|op| {
|
||||
if op.status == OperationStatus::Running
|
||||
&& now.saturating_sub(op.started_at) > 600
|
||||
{
|
||||
false // Remove stale operations
|
||||
} else {
|
||||
true
|
||||
if op.status == OperationStatus::Running {
|
||||
if !is_process_alive(op.pid) {
|
||||
return false; // Remove dead operations
|
||||
}
|
||||
if now.saturating_sub(op.started_at) > 600 {
|
||||
return false; // Remove old operations
|
||||
}
|
||||
}
|
||||
true
|
||||
});
|
||||
|
||||
if stale_count > 0 {
|
||||
|
|
@ -311,7 +333,9 @@ impl IpcCoordinator {
|
|||
let conflicting: Vec<_> = operations
|
||||
.iter()
|
||||
.filter(|op| {
|
||||
op.r#type == operation_type && op.status == OperationStatus::Running
|
||||
op.r#type == operation_type
|
||||
&& op.status == OperationStatus::Running
|
||||
&& is_process_alive(op.pid)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
@ -403,7 +427,9 @@ impl IpcCoordinator {
|
|||
let conflicts: Vec<_> = operations
|
||||
.iter()
|
||||
.filter(|op| {
|
||||
op.r#type == operation_type && op.status == OperationStatus::Running
|
||||
op.r#type == operation_type
|
||||
&& op.status == OperationStatus::Running
|
||||
&& is_process_alive(op.pid)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
@ -426,7 +452,9 @@ impl IpcCoordinator {
|
|||
pub fn has_running_operation(&self, operation_type: OperationType) -> bool {
|
||||
let operations = self.load_operations().unwrap_or_default();
|
||||
operations.iter().any(|op| {
|
||||
op.r#type == operation_type && op.status == OperationStatus::Running
|
||||
op.r#type == operation_type
|
||||
&& op.status == OperationStatus::Running
|
||||
&& is_process_alive(op.pid)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -439,7 +467,9 @@ impl IpcCoordinator {
|
|||
operations
|
||||
.into_iter()
|
||||
.filter(|op| {
|
||||
op.r#type == operation_type && op.status == OperationStatus::Running
|
||||
op.r#type == operation_type
|
||||
&& op.status == OperationStatus::Running
|
||||
&& is_process_alive(op.pid)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue