Files
rust/tests/ui/zombie_processes.rs
T
Samuel Tardieu 3c8bfd144b zombie_processes: do not complain about early early returns
If an early return is found under the HIR local declaration node but
before the child process is created, it should not trigger the lint
because the child process has not yet been created.
2025-05-28 20:40:05 +02:00

211 lines
4.8 KiB
Rust

#![warn(clippy::zombie_processes)]
#![allow(clippy::if_same_then_else, clippy::ifs_same_cond, clippy::needless_return)]
use std::process::{Child, Command, ExitStatus};
fn main() {
{
// Check that #[expect] works
#[expect(clippy::zombie_processes)]
let mut x = Command::new("").spawn().unwrap();
}
{
let mut x = Command::new("").spawn().unwrap();
//~^ zombie_processes
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();
//~^ zombie_processes
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();
//~^ zombie_processes
if true {
std::process::exit(0);
}
}
{
let mut x = Command::new("").spawn().unwrap();
//~^ zombie_processes
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();
//~^ zombie_processes
if true {
return;
}
x.wait().unwrap();
}
{
let mut x = Command::new("").spawn().unwrap();
//~^ zombie_processes
if true {
x.wait().unwrap();
}
}
{
let mut x = Command::new("").spawn().unwrap();
//~^ zombie_processes
if true {
x.wait().unwrap();
} else {
// this else block exists to test the other help message
}
}
{
let mut x = Command::new("").spawn().unwrap();
//~^ zombie_processes
if true {
// this else block exists to test the other help message
} else {
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();
}
{
let mut x = Command::new("").spawn().unwrap();
std::thread::spawn(move || {
x.wait().unwrap();
});
}
}
fn process_child(c: Child) {
todo!()
}
fn return_wait() -> ExitStatus {
let mut x = Command::new("").spawn().unwrap();
return x.wait().unwrap();
}
mod issue14677 {
use std::io;
use std::process::Command;
fn do_something<F: Fn() -> Result<(), ()>>(f: F) {
todo!()
}
fn foo() {
let mut child = Command::new("true").spawn().unwrap();
let some_condition = true;
do_something(|| {
if some_condition {
return Err(());
}
Ok(())
});
child.kill().unwrap();
child.wait().unwrap();
}
}
fn issue14911() -> std::io::Result<String> {
let (mut recv, send) = std::io::pipe()?;
let mut command = Command::new("ls")
.stdout(send.try_clone()?)
.spawn()
.expect("Could not spawn new process...");
command.wait()?;
Ok("".into())
}