Skip to content

Commit

Permalink
chore: Bump procfs
Browse files Browse the repository at this point in the history
  • Loading branch information
Nukesor committed Aug 22, 2022
1 parent afd9d53 commit 67aa1b9
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 18 deletions.
53 changes: 50 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,4 @@ serde_yaml = "0.9"
[target.'cfg(any(target_os = "linux", target_os = "freebsd"))'.dependencies]
nix = "0.24"
whoami = "1"
procfs = { version = "0.12", default-features = false }
procfs = { version = "0.14", default-features = false }
2 changes: 1 addition & 1 deletion lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,4 @@ whoami = "1"

# Linux / Freebsd
[target.'cfg(any(target_os = "linux", target_os = "freebsd"))'.dependencies]
procfs = { version = "0.12", default-features = false }
procfs = { version = "0.14", default-features = false }
46 changes: 33 additions & 13 deletions lib/src/process_helper/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ fn send_signal_to_processes(processes: Vec<Process>, signal: Signal) {
}

/// Get all children of a specific process
fn get_child_processes(pid: i32) -> Vec<Process> {
fn get_child_processes(ppid: i32) -> Vec<Process> {
let all_processes = match all_processes() {
Err(error) => {
warn!("Failed to get full process list: {error}");
Expand All @@ -269,9 +269,18 @@ fn get_child_processes(pid: i32) -> Vec<Process> {
Ok(processes) => processes,
};

// Get all processes whose `stat` can be access without any errors.
// We then search for processes with the correct parent process id.
all_processes
.into_iter()
.filter(|process| process.stat.ppid == pid)
.filter_map(|process| process.ok())
.filter(|process| {
if let Ok(stat) = process.stat() {
stat.ppid == ppid
} else {
false
}
})
.collect()
}

Expand All @@ -288,6 +297,7 @@ mod tests {
use std::thread::sleep;
use std::time::Duration;

use anyhow::Result;
use pretty_assertions::assert_eq;

use super::*;
Expand All @@ -310,7 +320,7 @@ mod tests {

#[test]
/// Ensure a `sh -c` command will be properly killed without detached processes.
fn test_shell_command_is_killed() {
fn test_shell_command_is_killed() -> Result<()> {
let mut child = compile_shell_command("sleep 60 & sleep 60 && echo 'this is a test'")
.spawn()
.expect("Failed to spawn echo");
Expand All @@ -336,14 +346,16 @@ mod tests {

// Assert that all child processes have been killed.
for child_process in child_processes {
assert!(process_is_gone(child_process.stat.pid));
assert!(!child_process.is_alive());
}

Ok(())
}

#[test]
/// Ensure a `sh -c` command will be properly killed without detached processes when using unix
/// signals directly.
fn test_shell_command_is_killed_with_signal() {
fn test_shell_command_is_killed_with_signal() -> Result<()> {
let child = compile_shell_command("sleep 60 & sleep 60 && echo 'this is a test'")
.spawn()
.expect("Failed to spawn echo");
Expand All @@ -369,14 +381,16 @@ mod tests {

// Assert that all child processes have been killed.
for child_process in child_processes {
assert!(process_is_gone(child_process.stat.pid));
assert!(!child_process.is_alive());
}

Ok(())
}

#[test]
/// Ensure that a `sh -c` process with a child process that has children of its own
/// will properly kill all processes and their children's children without detached processes.
fn test_shell_command_children_are_killed() {
fn test_shell_command_children_are_killed() -> Result<()> {
let mut child = compile_shell_command("bash -c 'sleep 60 && sleep 60' && sleep 60")
.spawn()
.expect("Failed to spawn echo");
Expand All @@ -393,7 +407,7 @@ mod tests {
assert_eq!(child_processes.len(), 1);
let mut childrens_children = Vec::new();
for child_process in &child_processes {
childrens_children.extend(get_child_processes(child_process.stat.pid));
childrens_children.extend(get_child_processes(child_process.stat()?.pid));
}
assert_eq!(childrens_children.len(), 1);

Expand All @@ -408,18 +422,20 @@ mod tests {

// Assert that all child processes have been killed.
for child_process in child_processes {
assert!(process_is_gone(child_process.stat.pid));
assert!(!child_process.is_alive());
}

// Assert that all children's child processes have been killed.
for child_process in childrens_children {
assert!(process_is_gone(child_process.stat.pid));
assert!(!child_process.is_alive());
}

Ok(())
}

#[test]
/// Ensure a normal command without `sh -c` will be killed.
fn test_normal_command_is_killed() {
fn test_normal_command_is_killed() -> Result<()> {
let mut child = Command::new("sleep")
.arg("60")
.spawn()
Expand All @@ -442,12 +458,14 @@ mod tests {
sleep(Duration::from_millis(500));

assert!(process_is_gone(pid));

Ok(())
}

#[test]
/// Ensure a normal command and all its children will be
/// properly killed without any detached processes.
fn test_normal_command_children_are_killed() {
fn test_normal_command_children_are_killed() -> Result<()> {
let mut child = Command::new("bash")
.arg("-c")
.arg("sleep 60 & sleep 60 && sleep 60")
Expand Down Expand Up @@ -475,7 +493,9 @@ mod tests {

// Assert that all child processes have been killed.
for child_process in child_processes {
assert!(process_is_gone(child_process.stat.pid));
assert!(!child_process.is_alive());
}

Ok(())
}
}

0 comments on commit 67aa1b9

Please sign in to comment.