#subprocess #events #unix #loops #multiprocessing #event-source

bin+lib calloop-subproc

为 Calloop 事件循环提供子进程支持

1 个稳定版本

1.0.0 2022 年 5 月 12 日

#565Unix API

MIT 许可证

37KB
455

Maintenance License Coverage Rust

calloop-subprocess

Calloop 事件循环 提供子进程处理事件源。

Calloop 是围绕 事件源 概念构建的,例如计时器、通道、文件描述符本身,它们生成事件并调用回调函数。这个包提供了两种事件源,让您管理子进程

  • a ,它运行一系列命令并生成成功/失败事件
  • a 监听器,它运行单个命令并根据输出行生成事件

错误处理

此包中的错误分为两种高级类型,与 Calloop 的自定义相同。

LaunchError 可能由事件源的 process_events() 方法在遇到关键错误时生成。这通常意味着事件源本身无法继续合理地进行,应该从事件循环中移除。

ErrorEvent 类型涉及它所管理的子进程的错误,包括命令找不到或需要进程没有的权限。这些将包含在提供给回调的事件类型中。

这些不同的主要方式是:如果我们使用的基础机制在创建子进程或从它获取结果时出现问题时,则会立即生成一个 LaunchError。但如果设置子进程的基础机制成功,只是命令中有拼写错误找不到,则可以生成一个事件。它只会包含您在直接尝试运行命令时预期的 IO 错误

释放文件描述符

为了避免“持有”文件描述符(以及与事件源本身相关的内存),您必须遵守从calloop::PostAction 返回的,并删除请求的事件源。

对于顶级事件源,这会自动完成,即通过 insert_source() 添加的事件源。如果您将其作为组合事件源的一部分使用,您必须自己管理重新注册,或者用 TransientSource 包装源。

示例

此代码执行 ls -a 并打印收到的事件。

use calloop::{EventLoop, LoopSignal};
use calloop_subproc::{Command, SubprocListen};

let ls_cmd = Command::new("ls").with_args(["-a"]);
let listener = SubprocListen::new(ls_cmd).unwrap();

let mut event_loop: EventLoop<LoopSignal> = EventLoop::try_new().unwrap();

event_loop
    .handle()
    .insert_source(listener, |event, _, stopper| {
        // What kind of event did we get this time?
        let msg = match event {
            // The subprocess was just started.
            calloop_subproc::ListenEvent::Start => "Subprocess started".to_owned(),
            // We got a line of output from the subprocess.
            calloop_subproc::ListenEvent::Line(line) => format!("Output: {}", line),
            // The subprocess ended.
            calloop_subproc::ListenEvent::End(res) => {
                // Since the subprocess ended, we want to stop the loop.
                stopper.stop();

                // Show why the subprocess ended.
                match res {
                    Ok(()) => "Subprocess completed".to_owned(),
                    Err(error) => format!("Subprocess error: {:?}", error),
                }
            }
        };

        // Print our formatted event.
        println!("{}", msg);

        // This callback must return true if the subprocess should be
        // killed. We want it to run to completion, so we return false.
        false
    })
    .unwrap();

event_loop
    .run(None, &mut event_loop.get_signal(), |_| {})
    .unwrap();

此文档使用 cargo-rdme 保持最新。

依赖关系

~6–19MB
~235K SLoC