我生成了一个子进程,

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

我想在执行结束时杀死子进程(当主进程终止时).我发现这是一项艰巨的任务,

  1. 似乎没有简单的方法来注册要在rust中运行的函数.我得用libc::atexit()个.
  2. 我不知道如何将参数传递给rust中的C函数指针.所以我得用一个全球性的虚拟机
  3. 我不知道如何将std::process::Child存储为一个全局的静态变量,而不定义它.如果我简单地将static mut CHILD_PROCESS: std::process::Child;放在文件的开头,它会给出错误free static item without body.

下面是我设法产生的复杂的解决方案:

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 剂?

推荐答案

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

假设你有panic = "unwind"个,最安全的 Select 是在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()似乎是唯一的 Select ,但要注意上面的警告.

Rust相关问答推荐

捕获Rust因C++异常而产生panic

使用Rust s serde_json对混合数据类型进行优化'

如何处理动态 struct 实例化?

在Rust中赋值变量有运行时开销吗?

Box::new()会从一个堆栈复制到另一个堆吗?

获取字符串切片(&;str)上的切片([ia..ib])返回字符串

将PathBuf转换为字符串

函数内模块的父作用域的访问类型

为昂贵的for循环制作筛子

将Vec<;U8&>转换为Vec<;{Float}&>

如何设置activx websocket actorless的消息大小限制?

为相同特征的特征对象使用 move 方法实现特征

我可以解构self 参数吗?

如何将一个矩阵的列分配给另一个矩阵,纳尔代数?

使用启用优化的 alloc 会导致非法指令崩溃

Rust 中的复合 `HashSet` 操作或如何在 Rust 中获得 `HashSet` 的显式差异/并集

pyO3 和 Panics

std::vector::shrink_to_fit 如何在 Rust 中工作?

以 `static` 为前缀的闭包是什么意思?我什么时候使用它?

为什么这里需要类型注解?