Rust 执行完成后杀死 std::process::Child

问题描述 投票:0回答:1

我生成了一个子进程:

let child = Command::new("./chromedriver")
    .spawn()
    .expect("Failed To Run Chromedriver");

我想在主进程终止时执行结束时杀死它。我发现这是一项艰巨的任务:

  1. Rust 似乎没有简单的方法来注册要在进程结束时运行的函数。我必须使用像
    libc::atexit()
    这样的东西。
  2. 我不知道如何在 Rust 中将参数传递给 C 函数指针。所以我必须使用全局变量
  3. 我不知道如何将
    std::process::Child
    存储为全局静态变量而不定义它。如果我简单地将
    free static item without body
    放在文件的开头,它会给出错误
    static mut CHILD_PROCESS: std::process::Child;

所以这是我设法产生的复杂解决方案:

static mut CHILD_PROCESS_ID: i32 = 0;

extern "C" fn kill_child() {
    unsafe {
        let pid: libc::pid_t = CHILD_PROCESS_ID;
        libc::kill(pid, libc::SIGKILL);
    }
}

fn run_chrome_driver() {
    let child = Command::new("./chromedriver")
        .spawn()
        .expect("Failed To Run Chromedriver");
    unsafe {
        let id: i32 = child.id().try_into().unwrap();
        CHILD_PROCESS_ID = id;
        libc::atexit(kill_child);
    }
}

有没有更好的方法而不使用不安全的 Rust?

rust child-process kill
1个回答
3
投票

atexit()
可能不是 你想要的。由于它是在 Rust 考虑进程退出后执行的,因此从其中使用any标准库 API 是不安全的。因此,将其封装在安全的 API 中几乎是不可能的。您将不得不使用不安全。

假设你有

panic = "unwind"
,最安全的选择是在
main()
中有一个会杀死孩子的空投守卫。这看起来像:

use std::process::{Child, Command};
use std::sync::Mutex;

static CHILD: Mutex<Option<Child>> = Mutex::new(None);

struct KillChildGuard;
impl Drop for KillChildGuard {
    fn drop(&mut self) {
        let child = CHILD.lock().unwrap().take();
        if let Some(mut child) = child {
            child.kill().expect("failed to kill");
        }
    }
}

fn main() {
    let _guard = KillChildGuard;

    // Anywhere inside the code, even deep in functions:
    let child = Command::new("./chromedriver")
        .spawn()
        .expect("Failed To Run Chromedriver");
    *CHILD.lock().unwrap() = Some(child);
}

如果您有

panic = "abort"
,那么
atexit()
似乎是唯一的选择,但请注意上述警告。

© www.soinside.com 2019 - 2024. All rights reserved.