I'm writing a small test that starts a daemon process and tests it e.g:
let server = Command::new("target/debug/server").spawn();
// do some tests
server.kill();
The typical way to fail a test is to panic. Unfortunately this means that kill() never gets invoked and repeated runs of the test suite fail, because the port is taken by the old process that is still running.
Is there something like a TRAP function that I can use to ensure the Child gets killed?
You can use standard RAII patterns to ensure the child thread is killed if you leave a given scope. If you want to kill your child only if you are panicking, you can insert a check to std::thread::panicking.
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"),
}
}
}
fn main() {
let child = Command::new("/bin/cat").spawn().unwrap();
let _guard = ChildGuard(child);
panic!("Main thread panicking");
}
You can put the possibly-panicking code into a closure and give that closure to catch_panic
. catch_panic
acts the same way a scoped
or spawn
ed thread does on join
ing. It returns a Result with either Ok(ClosureRetVal)
or an Err(Box<Any>)
if the closure panicked.
let res = std::thread::catch_panic(|| {
panic!("blub: {}", 35);
});
if let Err(err) = res {
let msg: String = *err.downcast().unwrap();
println!("{}", msg);
}
PlayPen
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With