Hello,
I'm making a program that has many long running tasks in the background and when it panics those processes keep running which I don't want. I run the Command::new("something").spawn().wait()
in a separate thread (which I don't join) because I need to wrap it in an infinite loop in case the command terminates unexpectedly.
I tried having a global Arc<Mutex<Vec<Child>>>
but that didn't work because after having moved the value inside I can't wait
on it anymore, because (I think) wait takes a &mut self
.
I have tried wrapping the Child
into a struct and implementing Drop
for it and that doesn't really work, here are the things I tried.
Any idea?
use std::process::{Command,Child};
struct ChildGuard(Child);
impl Drop for ChildGuard {
fn drop(&mut self) {
// You can check std::thread::panicking() here
match self.0.kill() {
Err(e) => println!("Could not kill child process: {}", e),
Ok(_) => println!("Successfully killed child process"),
}
}
}
/* Content of hang.sh
#! /bin/sh
echo "Starting hang"
sleep 6
echo "Ending hang"
*/
fn main() {
//main1();
main2();
//main3();
}
// Child process keep running in background after panic
fn main1() {
let t = std::thread::spawn(move || {
let child = Command::new("./hang.sh").spawn().unwrap();
let mut _guard = ChildGuard(child);
_guard.0.wait();
});
std::thread::sleep(std::time::Duration::from_secs(4));
panic!("Main thread panicking");
}
// Child process keep running in background after panic
fn main2() {
let t = std::thread::spawn(move || {
let child = Command::new("./hang.sh").spawn().unwrap();
let mut _guard = ChildGuard(child);
std::thread::sleep(std::time::Duration::from_secs(2));
panic!("Sub thread panicking");
});
t.join();
}
// Child process terminates
fn main3() {
let t = std::thread::spawn(move || {
let child = Command::new("./hang.sh").spawn().unwrap();
let mut _guard = ChildGuard(child);
std::thread::sleep(std::time::Duration::from_secs(2));
panic!("Sub thread panicking");
});
std::thread::sleep(std::time::Duration::from_secs(4));
panic!("Main thread panicking");
}