Как я могу гарантировать, что порожденный дочерний процесс будет убит в случае паники моего приложения?

Я пишу небольшой тест, который запускает процесс демона и проверяет его, например:

let server = Command::new("target/debug/server").spawn();

// do some tests

server.kill();

Типичный способ провалить тест - запаниковать. К сожалению, это означает, что kill () никогда не вызывается, а повторные запуски набора тестов завершаются ошибкой, потому что порт занят старым процессом, который все еще работает.

Есть ли что-то вроде функции ЛОВУШКИ, которую я могу использовать, чтобы убивать ребенка?


person j16r    schedule 29.05.2015    source источник


Ответы (2)


Вы можете поместить код, который может вызвать панику, в закрытие и дать это закрытие catch_panic. catch_panic действует так же, как поток scoped или spawned при joining. Он возвращает Результат либо с Ok(ClosureRetVal), либо с Err(Box<Any>), если закрытие вызвало панику.

let res = std::thread::catch_panic(|| {
    panic!("blub: {}", 35);
});
if let Err(err) = res {
    let msg: String = *err.downcast().unwrap();
    println!("{}", msg);
}

PlayPen

person oli_obk    schedule 29.05.2015

Вы можете использовать стандартные шаблоны RAII, чтобы гарантировать, что дочерний поток будет убит, если вы покинете заданную область. Если вы хотите убить своего ребенка только в случае паники, вы можете вставить чек в 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");
}
person Vaelden    schedule 29.05.2015
comment
Гарантируется ли запуск реализаций Drop в случае паники потока? - person Shepmaster; 30.05.2015
comment
Я так думаю, если только паника не была начата в деструкторе (манеж), который в любом случае это плохая идея в Rust по разным причинам. Существует некоторая документация о том, как происходит процесс раскрутки в std :: rt :: unwind < / а>. - person Vaelden; 30.05.2015
comment
Спасибо, примерно этим я и закончил. Хотя теперь, поскольку у меня есть это в Once, похоже, нет возможности выполнить трейт Drop. - person j16r; 31.05.2015