|
| 1 | +//! Tests that repeatedly spawning a failing command does not create zombie processes. |
| 2 | +//! Spawns a deliberately invalid command multiple times, verifies each spawn fails, |
| 3 | +//! then uses `ps` (on Unix) to detect any leftover zombie (defunct) child processes. |
| 4 | +//! Checks Rust's process spawning cleans up resources properly. |
| 5 | +//! Skipped on platforms without `ps` utility. |
| 6 | +
|
1 | 7 | //@ run-pass
|
2 | 8 | //@ needs-subprocess
|
3 | 9 | //@ ignore-vxworks no 'ps'
|
@@ -36,35 +42,42 @@ fn find_zombies() {
|
36 | 42 | // the PPID column contains a "-" for the respective process.
|
37 | 43 | // Filter out any lines that have a "-" as the PPID as the PPID is
|
38 | 44 | // expected to be an integer.
|
39 |
| - let filtered_ps: Vec<_> = ps_output |
40 |
| - .lines() |
41 |
| - .filter(|line| line.split_whitespace().nth(1) != Some("-")) |
42 |
| - .collect(); |
| 45 | + let filtered_ps: Vec<_> = |
| 46 | + ps_output.lines().filter(|line| line.split_whitespace().nth(1) != Some("-")).collect(); |
43 | 47 |
|
44 | 48 | for (line_no, line) in filtered_ps.into_iter().enumerate() {
|
45 |
| - if 0 < line_no && 0 < line.len() && |
46 |
| - my_pid == line.split(' ').filter(|w| 0 < w.len()).nth(1) |
47 |
| - .expect("1st column should be PPID") |
48 |
| - .parse().ok() |
49 |
| - .expect("PPID string into integer") && |
50 |
| - line.contains("defunct") { |
| 49 | + if 0 < line_no |
| 50 | + && 0 < line.len() |
| 51 | + && my_pid |
| 52 | + == line |
| 53 | + .split(' ') |
| 54 | + .filter(|w| 0 < w.len()) |
| 55 | + .nth(1) |
| 56 | + .expect("1st column should be PPID") |
| 57 | + .parse() |
| 58 | + .ok() |
| 59 | + .expect("PPID string into integer") |
| 60 | + && line.contains("defunct") |
| 61 | + { |
51 | 62 | panic!("Zombie child {}", line);
|
52 | 63 | }
|
53 | 64 | }
|
54 | 65 | }
|
55 | 66 |
|
56 | 67 | #[cfg(windows)]
|
57 |
| -fn find_zombies() { } |
| 68 | +fn find_zombies() {} |
58 | 69 |
|
59 | 70 | fn main() {
|
60 | 71 | let too_long = format!("/NoSuchCommand{:0300}", 0u8);
|
61 | 72 |
|
62 |
| - let _failures = (0..100).map(|_| { |
63 |
| - let mut cmd = Command::new(&too_long); |
64 |
| - let failed = cmd.spawn(); |
65 |
| - assert!(failed.is_err(), "Make sure the command fails to spawn(): {:?}", cmd); |
66 |
| - failed |
67 |
| - }).collect::<Vec<_>>(); |
| 73 | + let _failures = (0..100) |
| 74 | + .map(|_| { |
| 75 | + let mut cmd = Command::new(&too_long); |
| 76 | + let failed = cmd.spawn(); |
| 77 | + assert!(failed.is_err(), "Make sure the command fails to spawn(): {:?}", cmd); |
| 78 | + failed |
| 79 | + }) |
| 80 | + .collect::<Vec<_>>(); |
68 | 81 |
|
69 | 82 | find_zombies();
|
70 | 83 | // then _failures goes out of scope
|
|
0 commit comments