rskit-process 0.1.0-alpha.1

Process and subprocess execution with timeout and signal handling
Documentation
use std::io;
use std::process::Stdio;

use tokio::process::Command as TokioCommand;

use crate::{EnvPolicy, ProcessConfig, ProcessSpec};

pub(in crate::runner) fn configure_command(
    cmd: &mut TokioCommand,
    spec: &ProcessSpec,
    config: &ProcessConfig,
    stdin: Stdio,
    stdout: Stdio,
    stderr: Stdio,
) {
    cmd.args(&spec.args)
        .stdin(stdin)
        .stdout(stdout)
        .stderr(stderr);

    if let Some(dir) = &spec.dir {
        cmd.current_dir(dir);
    }

    if matches!(spec.env_policy, EnvPolicy::Empty) {
        cmd.env_clear();
    }
    for (key, value) in &spec.env {
        cmd.env(key, value);
    }

    if config.signal.create_process_group {
        isolate(cmd);
    }
}

fn isolate(cmd: &mut TokioCommand) {
    #[cfg(unix)]
    // SAFETY: `pre_exec` runs in the child process after fork and before exec.
    // The closure only calls the async-signal-safe `setpgid` libc function and
    // returns an `io::Error` on failure, which is the supported usage pattern.
    unsafe {
        cmd.pre_exec(|| {
            if libc::setpgid(0, 0) != 0 {
                return Err(io::Error::last_os_error());
            }
            Ok(())
        });
    }
}