Skip to content

Commit 46dee87

Browse files
committed
windows: replace local pipe spawning
1 parent 24d6479 commit 46dee87

7 files changed

Lines changed: 488 additions & 39 deletions

File tree

codex-rs/utils/pty/src/pipe.rs

Lines changed: 51 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,56 @@
11
use std::collections::HashMap;
2+
#[cfg(not(windows))]
23
use std::io;
4+
#[cfg(not(windows))]
35
use std::io::ErrorKind;
46
use std::path::Path;
7+
#[cfg(not(windows))]
58
use std::process::Stdio;
9+
#[cfg(not(windows))]
610
use std::sync::Arc;
11+
#[cfg(not(windows))]
712
use std::sync::Mutex as StdMutex;
13+
#[cfg(not(windows))]
814
use std::sync::atomic::AtomicBool;
915

1016
use anyhow::Result;
17+
#[cfg(not(windows))]
1118
use tokio::io::AsyncRead;
19+
#[cfg(not(windows))]
1220
use tokio::io::AsyncReadExt;
21+
#[cfg(not(windows))]
1322
use tokio::io::AsyncWriteExt;
23+
#[cfg(not(windows))]
1424
use tokio::io::BufReader;
25+
#[cfg(not(windows))]
1526
use tokio::process::Command;
27+
#[cfg(not(windows))]
1628
use tokio::sync::mpsc;
29+
#[cfg(not(windows))]
1730
use tokio::sync::oneshot;
31+
#[cfg(not(windows))]
1832
use tokio::task::JoinHandle;
1933

34+
#[cfg(not(windows))]
2035
use crate::process::ChildTerminator;
36+
#[cfg(not(windows))]
2137
use crate::process::ProcessHandle;
38+
#[cfg(not(windows))]
2239
use crate::process::ProcessSignal;
2340
use crate::process::SpawnedProcess;
41+
#[cfg(not(windows))]
2442
use crate::process::exit_code_from_status;
2543

2644
#[cfg(target_os = "linux")]
2745
use libc;
2846

47+
#[cfg(not(windows))]
2948
struct PipeChildTerminator {
30-
#[cfg(windows)]
31-
pid: u32,
3249
#[cfg(unix)]
3350
process_group_id: u32,
3451
}
3552

53+
#[cfg(not(windows))]
3654
impl ChildTerminator for PipeChildTerminator {
3755
fn signal(&mut self, signal: ProcessSignal) -> io::Result<()> {
3856
match signal {
@@ -56,36 +74,14 @@ impl ChildTerminator for PipeChildTerminator {
5674
crate::process_group::kill_process_group(self.process_group_id)
5775
}
5876

59-
#[cfg(windows)]
60-
{
61-
kill_process(self.pid)
62-
}
63-
6477
#[cfg(not(any(unix, windows)))]
6578
{
6679
Ok(())
6780
}
6881
}
6982
}
7083

71-
#[cfg(windows)]
72-
fn kill_process(pid: u32) -> io::Result<()> {
73-
unsafe {
74-
let handle = winapi::um::processthreadsapi::OpenProcess(
75-
winapi::um::winnt::PROCESS_TERMINATE,
76-
0,
77-
pid,
78-
);
79-
if handle.is_null() {
80-
return Err(io::Error::last_os_error());
81-
}
82-
let success = winapi::um::processthreadsapi::TerminateProcess(handle, 1);
83-
let err = io::Error::last_os_error();
84-
winapi::um::handleapi::CloseHandle(handle);
85-
if success == 0 { Err(err) } else { Ok(()) }
86-
}
87-
}
88-
84+
#[cfg(not(windows))]
8985
async fn read_output_stream<R>(mut reader: R, output_tx: mpsc::Sender<Vec<u8>>)
9086
where
9187
R: AsyncRead + Unpin,
@@ -103,12 +99,14 @@ where
10399
}
104100
}
105101

102+
#[cfg(not(windows))]
106103
#[derive(Clone, Copy)]
107104
enum PipeStdinMode {
108105
Piped,
109106
Null,
110107
}
111108

109+
#[cfg(not(windows))]
112110
async fn spawn_process_with_stdin_mode(
113111
program: &str,
114112
args: &[String],
@@ -240,8 +238,6 @@ async fn spawn_process_with_stdin_mode(
240238
let handle = ProcessHandle::new(
241239
writer_tx,
242240
Box::new(PipeChildTerminator {
243-
#[cfg(windows)]
244-
pid,
245241
#[cfg(unix)]
246242
process_group_id,
247243
}),
@@ -271,7 +267,16 @@ pub async fn spawn_process(
271267
env: &HashMap<String, String>,
272268
arg0: &Option<String>,
273269
) -> Result<SpawnedProcess> {
274-
spawn_process_with_stdin_mode(program, args, cwd, env, arg0, PipeStdinMode::Piped, &[]).await
270+
#[cfg(windows)]
271+
{
272+
let _ = arg0;
273+
crate::win::pipe::spawn_process(program, args, cwd, env).await
274+
}
275+
#[cfg(not(windows))]
276+
{
277+
spawn_process_with_stdin_mode(program, args, cwd, env, arg0, PipeStdinMode::Piped, &[])
278+
.await
279+
}
275280
}
276281

277282
/// Spawn a process using regular pipes, but close stdin immediately.
@@ -295,14 +300,22 @@ pub async fn spawn_process_no_stdin_with_inherited_fds(
295300
arg0: &Option<String>,
296301
inherited_fds: &[i32],
297302
) -> Result<SpawnedProcess> {
298-
spawn_process_with_stdin_mode(
299-
program,
300-
args,
301-
cwd,
302-
env,
303-
arg0,
304-
PipeStdinMode::Null,
305-
inherited_fds,
306-
)
307-
.await
303+
#[cfg(windows)]
304+
{
305+
let _ = (arg0, inherited_fds);
306+
crate::win::pipe::spawn_process_no_stdin(program, args, cwd, env).await
307+
}
308+
#[cfg(not(windows))]
309+
{
310+
spawn_process_with_stdin_mode(
311+
program,
312+
args,
313+
cwd,
314+
env,
315+
arg0,
316+
PipeStdinMode::Null,
317+
inherited_fds,
318+
)
319+
.await
320+
}
308321
}

codex-rs/utils/pty/src/process.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use core::fmt;
22
use std::io;
33
#[cfg(unix)]
44
use std::os::fd::RawFd;
5+
#[cfg(not(windows))]
56
use std::process::ExitStatus;
67
use std::sync::Arc;
78
use std::sync::Mutex as StdMutex;
@@ -32,6 +33,7 @@ pub(crate) fn unsupported_signal(signal: ProcessSignal) -> io::Error {
3233
}
3334
}
3435

36+
#[cfg(not(windows))]
3537
pub(crate) fn exit_code_from_status(status: ExitStatus) -> i32 {
3638
if let Some(code) = status.code() {
3739
return code;

codex-rs/utils/pty/src/tests.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ mod windows_job_test_support;
2828
#[path = "windows_conpty_job_tests.rs"]
2929
mod windows_conpty_job_tests;
3030

31+
#[cfg(windows)]
32+
#[path = "windows_pipe_job_tests.rs"]
33+
mod windows_pipe_job_tests;
34+
3135
fn find_python() -> Option<String> {
3236
for candidate in ["python3", "python"] {
3337
if let Ok(output) = std::process::Command::new(candidate)

codex-rs/utils/pty/src/win/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ use winapi::um::synchapi::WaitForSingleObject;
4040
use winapi::um::winbase::INFINITE;
4141
use winapi::um::winbase::WAIT_OBJECT_0;
4242

43-
#[cfg(test)]
4443
mod command;
4544
pub(crate) mod conpty;
4645
mod job;
46+
pub(crate) mod pipe;
4747
mod procthreadattr;
4848
mod psuedocon;
4949

0 commit comments

Comments
 (0)