diff --git a/crates/gpmcp-layer-core/src/process_manager_trait.rs b/crates/gpmcp-layer-core/src/process_manager_trait.rs index 90994c5..791f2e1 100644 --- a/crates/gpmcp-layer-core/src/process_manager_trait.rs +++ b/crates/gpmcp-layer-core/src/process_manager_trait.rs @@ -198,11 +198,14 @@ impl Decoder for Utf8Codec { } } pub async fn stream( - io: &mut A, + io: Option, out: impl Into, ) -> tokio::io::Result<()> { - let mut frames = FramedRead::with_capacity(io, Utf8Codec, 1024); - stream_frames(&mut frames, out.into()).await + if let Some(io) = io { + let mut frames = FramedRead::with_capacity(io, Utf8Codec, 1024); + return stream_frames(&mut frames, out.into()).await; + } + Ok(()) } async fn stream_frames( diff --git a/crates/gpmcp-layer-unix/src/unix_process_manager.rs b/crates/gpmcp-layer-unix/src/unix_process_manager.rs index a22118c..8933a98 100644 --- a/crates/gpmcp-layer-unix/src/unix_process_manager.rs +++ b/crates/gpmcp-layer-unix/src/unix_process_manager.rs @@ -216,23 +216,11 @@ impl ProcessManager for UnixProcessManager { ); } - // Capture and stream stdout - the stream function will detect it's stdout and route accordingly - if let Some(mut stdout) = child.stdout.take() { - tokio::spawn(async move { - if let Err(e) = stream(&mut stdout, out).await { - warn!("Error streaming stdout: {}", e); - } - }); - } + let (stdout, stderr) = (child.stdout.take(), child.stderr.take()); - // Capture and stream stderr - the stream function will detect it's stderr and route accordingly - if let Some(mut stderr) = child.stderr.take() { - tokio::spawn(async move { - if let Err(e) = stream(&mut stderr, err).await { - warn!("Error streaming stderr: {}", e); - } - }); - } + tokio::spawn( + async move { tokio::try_join!(stream(stdout, out), stream(stderr, err)).ok() }, + ); Ok(UnixProcessHandle::new(child, command.to_string())) } } diff --git a/crates/gpmcp-layer-windows/src/windows_process_manager.rs b/crates/gpmcp-layer-windows/src/windows_process_manager.rs index 96d86ca..9a03b3f 100644 --- a/crates/gpmcp-layer-windows/src/windows_process_manager.rs +++ b/crates/gpmcp-layer-windows/src/windows_process_manager.rs @@ -275,24 +275,11 @@ impl ProcessManager for WindowsProcessManager { ); } - // Capture and stream stdout - the stream function will detect it's stdout and route accordingly - if let Some(mut stdout) = child.stdout.take() { - tokio::spawn(async move { - if let Err(e) = stream(&mut stdout, out).await { - warn!("Error streaming stdout: {}", e); - } - }); - } - - // Capture and stream stderr - the stream function will detect it's stderr and route accordingly - if let Some(mut stderr) = child.stderr.take() { - tokio::spawn(async move { - if let Err(e) = stream(&mut stderr, err).await { - warn!("Error streaming stderr: {}", e); - } - }); - } + let (stdout, stderr) = (child.stdout.take(), child.stderr.take()); + tokio::spawn( + async move { tokio::try_join!(stream(stdout, out), stream(stderr, err)).ok() }, + ); Ok(WindowsProcessHandle::new(child, command.to_string())) } }