< 返回版块

eweca-d 发表于 2022-05-02 11:59

假设有如下的代码(task_pool是存储有任务状态的数据库):

    let child = Command::new("ffmpeg")
        .args(&[
            "-i",
            &src_video_name,
            "-vsync",
            "cfr",
            &dst_video_name,
        ])
        .current_dir(working_dir)
        .spawn()?;
    
     wait_child!(child, task_pool, id);

#[macro_export]
macro_rules! wait_child {
    ( $child: expr, $task_pool: expr, $id: expr ) => {{
        tokio::select! {
            res = $child.wait() => { if res.is_err() {
                $task_pool.mark_task_failed($id);
                return;
            } },
            _ = $task_pool.is_cancelled_task($id) => {
                #[allow(unused_variables)]
                let kill_res = $child.kill().await;
                return;
            },
        }
    }};
}

以上代码是可行的,当在task_pool中的该任务被标记为取消后,ffmpeg的任务当即取消。但假如使用:

    let child = Command::new("cmd")
        .args(&[
            "/C",
            "ffmpeg",
            "-i",
            &src_video_name,
            "-vsync",
            "cfr",
            &dst_video_name,
        ])
        .current_dir(working_dir)
        .spawn()?;
    
     wait_child!(child, task_pool, id);

这样就不可行了,退出的只有cmd和tokio运行时,但是ffmpeg仍然在进行工作。

以上程序包裹在tokio的运行时中,而通过rayon线程池,多进程地运行了很多类似的任务。如果暴力的panic进程,则整个进程池都会崩掉。

PS:以上只是一个例子,更麻烦的事情在于实际强制使用的是bat,不能使用类似Command::new ("ffmpeg")的方法直接调用,不知为何只能通过cmd调用。(但是手动运行bat时,可以通过"control + C"或者关闭窗口来退出所有相关进程)

使用了很多词条搜索,都没啥有用的解答。请教各位大佬,有没有什么方法,可以解决这个问题么?

评论区

写评论
作者 eweca-d 2022-05-04 00:56

对对对,我完全同意。cmd会创建一个或数个新进程。

如果直接使用cmd窗口调用bat,会发现,虽然有新进程,但是新进程会监视cmd的操作,如果cmd里输入^c,control + c,或者监视到cmd窗口被关闭,则子进程自动退出。(但问题是,command创建的cmd被kill后,新进程是检测不到窗口关闭这个事件的)

--
👇
sikasjc: 强答一波。。不熟悉windows,猜测是跟CMD创建进程的方式有关系

CMD.exe

Start a new CMD shell

“在windows上,a创建了b,b创建了c,b退出之后,c无法找到自己的爷爷进程。进程链就断了,c成为了一个顶端进程” from: https://www.zhihu.com/question/31429459/answer/51903852

作者 eweca-d 2022-05-04 00:52

感谢回答。但是原逻辑我试了行不通,ffmpeg可以通过这个办法进行,但是换个a.bat就不行了。麻烦之处在于这里。

--
👇
Nayaka: 提供个思路,但是手头没机器无法测试

依旧使用原逻辑,即Command::new("ffmpeg")...

正常执行与task kill返回不同的exit code, bat内用%errorlevel%处理exit code

sikasjc 2022-05-03 23:46

强答一波。。不熟悉windows,猜测是跟CMD创建进程的方式有关系

CMD.exe

Start a new CMD shell

“在windows上,a创建了b,b创建了c,b退出之后,c无法找到自己的爷爷进程。进程链就断了,c成为了一个顶端进程” from: https://www.zhihu.com/question/31429459/answer/51903852

Nayaka 2022-05-03 15:34

提供个思路,但是手头没机器无法测试

依旧使用原逻辑,即Command::new("ffmpeg")...

正常执行与task kill返回不同的exit code, bat内用%errorlevel%处理exit code

作者 eweca-d 2022-05-03 10:20

感谢大佬!我看了下,'tokio'里在unix类平台貌似就是kill -9。我用的windows,它不太能行。

--
👇
formoon: 在bash中这种情况要杀死进程组,kill -9 -进程组PID, 注意是进程组PID前面加一个负号。原来做golang的时候用syscall.Kill(),rust 没试过。

formoon 2022-05-02 16:06

在bash中这种情况要杀死进程组,kill -9 -进程组PID, 注意是进程组PID前面加一个负号。原来做golang的时候用syscall.Kill(),rust 没试过。

1 共 6 条评论, 1 页