acp_agent/runtime/
process.rs1use std::process::{ExitStatus, Stdio};
2
3use anyhow::{Context, Result};
4use tokio::process::{Child, Command};
5
6use crate::runtime::prepare::CommandSpec;
7
8pub fn apply_command_spec(command: &mut Command, spec: &CommandSpec) {
14 command.args(&spec.args);
15
16 if let Some(current_dir) = &spec.current_dir {
17 command.current_dir(current_dir);
18 }
19
20 for (key, value) in &spec.env {
21 command.env(key, value);
22 }
23}
24
25pub fn spawn_stream_child(spec: &CommandSpec, subject: &str) -> Result<Child> {
31 let program_display = spec.program.to_string_lossy().into_owned();
32 let mut command = Command::new(&spec.program);
33 apply_command_spec(&mut command, spec);
34 command
35 .stdin(Stdio::piped())
36 .stdout(Stdio::piped())
37 .stderr(Stdio::inherit());
38
39 command
40 .spawn()
41 .with_context(|| format!("failed to spawn {program_display} for {subject}"))
42}
43
44pub async fn terminate_child(child: &mut Child) -> Result<ExitStatus> {
50 if let Some(status) = child
51 .try_wait()
52 .context("failed while checking child process status")?
53 {
54 return Ok(status);
55 }
56
57 child
58 .kill()
59 .await
60 .context("failed to terminate child process")?;
61 child
62 .wait()
63 .await
64 .context("failed while waiting on child process")
65}