139 lines
3.5 KiB
Rust
139 lines
3.5 KiB
Rust
|
#![warn(clippy::zombie_processes)]
|
||
|
#![allow(clippy::if_same_then_else, clippy::ifs_same_cond)]
|
||
|
|
||
|
use std::process::{Child, Command};
|
||
|
|
||
|
fn main() {
|
||
|
{
|
||
|
// Check that #[expect] works
|
||
|
#[expect(clippy::zombie_processes)]
|
||
|
let mut x = Command::new("").spawn().unwrap();
|
||
|
}
|
||
|
|
||
|
{
|
||
|
let mut x = Command::new("").spawn().unwrap();
|
||
|
//~^ ERROR: spawned process is never `wait()`ed on
|
||
|
x.kill();
|
||
|
x.id();
|
||
|
}
|
||
|
{
|
||
|
let mut x = Command::new("").spawn().unwrap();
|
||
|
x.wait().unwrap(); // OK
|
||
|
}
|
||
|
{
|
||
|
let x = Command::new("").spawn().unwrap();
|
||
|
x.wait_with_output().unwrap(); // OK
|
||
|
}
|
||
|
{
|
||
|
let mut x = Command::new("").spawn().unwrap();
|
||
|
x.try_wait().unwrap(); // OK
|
||
|
}
|
||
|
{
|
||
|
let mut x = Command::new("").spawn().unwrap();
|
||
|
let mut r = &mut x;
|
||
|
r.wait().unwrap(); // OK, not calling `.wait()` directly on `x` but through `r` -> `x`
|
||
|
}
|
||
|
{
|
||
|
let mut x = Command::new("").spawn().unwrap();
|
||
|
process_child(x); // OK, other function might call `.wait()` so assume it does
|
||
|
}
|
||
|
{
|
||
|
let mut x = Command::new("").spawn().unwrap();
|
||
|
//~^ ERROR: spawned process is never `wait()`ed on
|
||
|
let v = &x;
|
||
|
// (allow shared refs is fine because one cannot call `.wait()` through that)
|
||
|
}
|
||
|
|
||
|
// https://github.com/rust-lang/rust-clippy/pull/11476#issuecomment-1718456033
|
||
|
// Unconditionally exiting the process in various ways (should not lint)
|
||
|
{
|
||
|
let mut x = Command::new("").spawn().unwrap();
|
||
|
std::process::exit(0);
|
||
|
}
|
||
|
{
|
||
|
let mut x = Command::new("").spawn().unwrap();
|
||
|
std::process::abort(); // same as above, but abort instead of exit
|
||
|
}
|
||
|
{
|
||
|
let mut x = Command::new("").spawn().unwrap();
|
||
|
if true { /* nothing */ }
|
||
|
std::process::abort(); // still unconditionally exits
|
||
|
}
|
||
|
|
||
|
// Conditionally exiting
|
||
|
// It should assume that it might not exit and still lint
|
||
|
{
|
||
|
let mut x = Command::new("").spawn().unwrap();
|
||
|
//~^ ERROR: spawned process is never `wait()`ed on
|
||
|
if true {
|
||
|
std::process::exit(0);
|
||
|
}
|
||
|
}
|
||
|
{
|
||
|
let mut x = Command::new("").spawn().unwrap();
|
||
|
//~^ ERROR: spawned process is never `wait()`ed on
|
||
|
if true {
|
||
|
while false {}
|
||
|
// Calling `exit()` after leaving a while loop should still be linted.
|
||
|
std::process::exit(0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
{
|
||
|
let mut x = { Command::new("").spawn().unwrap() };
|
||
|
x.wait().unwrap();
|
||
|
}
|
||
|
|
||
|
{
|
||
|
struct S {
|
||
|
c: Child,
|
||
|
}
|
||
|
|
||
|
let mut s = S {
|
||
|
c: Command::new("").spawn().unwrap(),
|
||
|
};
|
||
|
s.c.wait().unwrap();
|
||
|
}
|
||
|
|
||
|
{
|
||
|
let mut x = Command::new("").spawn().unwrap();
|
||
|
//~^ ERROR: spawned process is never `wait()`ed on
|
||
|
if true {
|
||
|
return;
|
||
|
}
|
||
|
x.wait().unwrap();
|
||
|
}
|
||
|
|
||
|
{
|
||
|
let mut x = Command::new("").spawn().unwrap();
|
||
|
//~^ ERROR: spawned process is never `wait()`ed on
|
||
|
if true {
|
||
|
x.wait().unwrap();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
{
|
||
|
let mut x = Command::new("").spawn().unwrap();
|
||
|
if true {
|
||
|
x.wait().unwrap();
|
||
|
} else if true {
|
||
|
x.wait().unwrap();
|
||
|
} else {
|
||
|
x.wait().unwrap();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
{
|
||
|
let mut x = Command::new("").spawn().unwrap();
|
||
|
if true {
|
||
|
x.wait().unwrap();
|
||
|
return;
|
||
|
}
|
||
|
x.wait().unwrap();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn process_child(c: Child) {
|
||
|
todo!()
|
||
|
}
|