Commit Graph
13 Commits
Author SHA1 Message Date
Maja Wichrowska 119a547a31 Prevent idle Windows MCP pipes from blocking unrelated I/O (#59726)
## Why

Idle reads from local MCP servers on Windows can occupy Tokio's blocking threads and delay unrelated filesystem operations.

## What changed

Use IOCP-backed named pipes for local MCP server stdin, stdout, and stderr on Windows. Connect child endpoints before launch, restrict pipe access to the owner and SYSTEM, and reject remote clients. Preserve the shared legacy and modern protocol framing.

## Testing

Add Windows regression tests to verify that idle MCP reads leave blocking I/O available in both protocol modes and that child output handles support querying the pipe mode.

GitOrigin-RevId: ca39b940a54427a2cd7bab5291011b0b09143b3f
2026-11-05 19:46:31 +00:00
Eric Traut fbc169827e Suppress Windows console windows for background subprocesses (#49164)
## Why

Background helpers launched from a detached Windows process can allocate console windows. Job Object launches and containment fallbacks need to preserve console suppression as well.

## What changed

- Add `codex_utils_process::background_command` to set `CREATE_NO_WINDOW` on Windows, and use it across background subprocess launches, including Git, plugins, authentication, diagnostics, and sandbox helpers.
- Centralize console suppression in Job Object launches. Keep `CREATE_NO_WINDOW` when retrying without containment, and clear `CREATE_SUSPENDED` so the fallback child can run.
- Preserve console inheritance for interactive shell launches and interactive AWS authentication refreshes.

## Testing

Add Windows regression tests covering console-free launches from detached parents through standard and Tokio commands, stdout/stderr capture, successful containment, Job Object creation and assignment failures, and sandbox setup refresh helpers.

GitOrigin-RevId: b2c238fa7d4f9fbd868e5adf7d4be9958ff01e6c
2026-09-29 04:38:37 +00:00
Felipe Coury 1a89aec960 Prevent console windows for piped Windows child processes (#48483)
## Why

Piped child processes launched from a detached Windows process should not allocate a console window.

## What changed

Set `CREATE_NO_WINDOW` by default for `codex-rs/utils/pty` child commands. Preserve it alongside `CREATE_SUSPENDED` when preparing a child for Job Object containment, since Tokio's `creation_flags` replaces existing flags.

## Testing

Add a Windows regression test that runs from a detached process and verifies that children have no console window and retain working piped stdin and stdout, both with and without Job Object containment.

GitOrigin-RevId: 990386032d74fa783a66bb20faff769539ea41c1
2026-09-26 16:46:08 +00:00
malsamiri-oai 4b9e0cc77f Suppress console windows for local Windows MCP servers (#48238)
## What changed

Expose Windows process creation flags on the shared command wrapper and use
`CREATE_NO_WINDOW` when launching local stdio MCP servers, including fallback
launches without Job Object containment. Preserve `CREATE_SUSPENDED` when
assigning the server to a Job Object before execution.

## Testing

Add a Windows regression test covering direct launches and launches through
`cmd.exe`. Verify that the server has no console, initializes successfully,
returns tools, and exits after shutdown.

GitOrigin-RevId: 84475e82999d91a431e09327d4f5639b59c01427
2026-09-25 22:56:00 +00:00
jif 51d4562070 Support close-on-exec attachments without changing PTY semantics (#47797)
## Why

Passing extra descriptors to a PTY previously selected behavior intended for inherited escalation sockets: no EOF on stdin close, different signal exit statuses, and no default `SHELL`. Launch attachments need ordinary PTY behavior and must survive execution even when marked `FD_CLOEXEC`.

## What changed

- Add `ChildFds::Attached` alongside `ChildFds::Inherited` to distinguish launch attachments from legacy inherited descriptors.
- Preserve ordinary EOF, default `SHELL`, and signal exit status behavior for PTY attachments.
- Allow explicitly supplied close-on-exec descriptors through pipe and PTY launches without changing the parent's descriptor flags, using child-side flag updates and macOS spawn inheritance actions.
- Update existing callers to use `ChildFds::Inherited`.

## Testing

Add Unix coverage for attachment accessibility, unchanged parent descriptor flags, default `SHELL`, and signal exit statuses. Extend the PTY stdin-draining test to cover attachments and EOF delivery.

GitOrigin-RevId: 864aedc6c5717d8b43c9d71057c9f54409834509
2026-09-24 09:25:19 +00:00
Yuzhu Shen b086ad5493 Make Linux descriptor cleanup fork-safe (#47654)
## Why

Linux descriptor cleanup used allocating directory enumeration after `fork`. The child needs allocation-free cleanup while preserving Rust's spawn-error channel until `exec` succeeds.

## What changed

- Mark unrelated descriptors close-on-exec with `close_range(CLOSE_RANGE_CLOEXEC)`, leaving stdio and explicitly preserved descriptors' flags untouched.
- Fall back to stack-backed `getdents64` enumeration of the child's descriptor table when `close_range` fails.
- Document best-effort cleanup: failures allow launch to proceed and may leave unrelated descriptors inherited.

## Testing

Add Linux tests for descriptor inheritance, unsorted and duplicate allowlists, unchanged parent descriptors, fallback cleanup above a lowered descriptor limit, preserved exec-error reporting, and successful launch when both cleanup paths fail. Retain MCP coverage for descriptor exclusion in servers and descendants.

GitOrigin-RevId: 13abb95f82557324c7b40feb36bd6f806d60674e
2026-09-23 20:20:06 +00:00
Charlie Marsh 88b498ded4 Route Linux PTY launches through the process setup helper (#47617)
## Why

PTY launches need to establish a controlling terminal and reset signal state. Extend the Linux process setup helper to perform this work in a fresh, single-threaded process image without forking the application when the native helper is available.

## What changed

- Add a PTY setup mode and support caller-owned stdout and stderr descriptors so all three standard streams use the PTY slave.
- Use the helper for eligible Linux PTY launches, including launches with explicitly preserved descriptors, and wait for child exit asynchronously.
- Preserve portable PTY behavior for `PATH` lookup, custom `argv[0]`, missing working directories, default `SHELL`, stdin EOF, and signal exit status.
- Retain compatibility fallbacks and release the initial PTY descriptors before allocating a portable replacement.

## Testing

Add regression tests for controlling-terminal setup without forking, portable signal exit status, and successful fallback under file-descriptor pressure. Resolve the Python test executable to an absolute path to exercise the helper path.

GitOrigin-RevId: 4b07ce68aa33c5b79548581e221caf5953b0eda1
2026-09-23 18:36:48 +00:00
Charlie Marsh 7aa6519909 Use native POSIX spawning for command hooks (#47610)
## Why

Unix command hooks use a `pre_exec` callback to detach from the controlling terminal, forcing the launcher to fork. Native spawn attributes can create the detached session without that callback.

## What changed

- Route Unix hooks through `codex_utils_pty::Command` with `ProcessMode::NewSession`.
- Extend the native `posix_spawn` launcher to detached Linux sessions, retaining compatibility fallbacks for unsupported libc features and executable handling.
- Preserve the session environment snapshot, hook overrides, and restricted-variable filtering.

## Testing

Add regression coverage for launches without parent forks, terminal detachment, environment and argument handling, Linux `PATH` lookup, and executable compatibility. Cover process-group cleanup on cancellation and timeout, including descendants holding output pipes open, and preservation of background descendants after completed hooks.

GitOrigin-RevId: dbe2cf12d84aa79868cfb55ace40c7d5b5282703
2026-09-23 18:24:05 +00:00
Charlie Marsh 50fc133d05 Route pipe processes through the shared child launcher (#47605)
## Why

Pipe spawning installs Unix `pre_exec` hooks, forcing a fork on macOS even though the shared child launcher supports native spawning.

## What changed

- Use the shared `Command` for pipe processes, enabling native macOS spawning while preserving session isolation, explicit descriptor inheritance, and Linux parent-death handling.
- Select `ReapOnly` so the pipe adapter retains ownership of process-tree termination.
- Track embedded NUL bytes in original Unix command inputs and reject them before spawning, including when invalid `current_dir` or `arg0` values are later replaced.

## Testing

Add macOS integration coverage verifying fork avoidance, executable path lookup, pipe I/O, session isolation, and descriptor inheritance. Add Unix regression tests for pipe and PTY fallback under descriptor pressure and for rejecting NUL inputs without running the child.

GitOrigin-RevId: f4fa2c1d3c1aee2c4ffa1dc2ff946f9f0b08eb20
2026-09-23 18:00:11 +00:00
Charlie Marsh b8d365b18e Extend child commands with session and descriptor controls (#47604)
## What changed

- Add `ProcessMode::NewSession`, null stdin, and opt-in Linux parent-death termination to the shared child command API.
- Replace `DescriptorPolicy::StdioOnly` with `Explicit` and add `preserve_fds` to allow selected inheritable Unix descriptors alongside stdio. Preserve descriptor numbers without duplicating or closing the parent's descriptors, keeping POSIX record locks intact.
- Support session creation and preserved descriptors in the native macOS backend, with a compatible fallback for high descriptor numbers rejected by native file actions.

## Testing

Add regression coverage for process groups and sessions, descriptor preservation across native and executable-text launches, the last descriptor slot below the file limit, and retention of parent record locks.

GitOrigin-RevId: 29ecd859d3b673da6ae6412cc06a32fa10d11346
2026-09-23 17:59:47 +00:00
Charlie Marsh 897b7ae285 Add a reap-only drop policy for child processes (#47603)
## What changed

Add a crate-private `ChildDropPolicy` to choose whether dropping a child kills it or only reaps it after exit. Keep `KillAndReap` as the default.

For `ReapOnly` on Unix, transfer dropped children to a shared reaper thread that operates independently of the Tokio runtime. Support both Tokio children and native macOS children, without blocking drop or letting a live child delay reaping others.

## Testing

Add an isolated regression test verifying that reap-only children survive handle drop after runtime shutdown, are reaped after exit, and do not prevent other exited children from being reaped.

GitOrigin-RevId: 5ec639597dba7f3b61694d6d465991e054ae3397
2026-09-23 17:59:23 +00:00
Charlie Marsh 595cc91e8c Avoid fork when spawning macOS filesystem helpers (#46661)
## Why

Filesystem helpers use a `pre_exec` callback to close inherited descriptors on macOS, forcing a fork before execution. Native spawning needs to preserve that isolation and support the socket used for file descriptor transfer.

## What changed

- Launch filesystem helpers through `codex_utils_pty::Command`, using `posix_spawn` with `POSIX_SPAWN_CLOEXEC_DEFAULT` on macOS and returning native launch errors without a fork fallback.
- Extend the shared command wrapper with explicit descriptor and fallback policies, socket-backed stdin, and custom `argv[0]` support.
- Add `Child::wait_with_output` to drain stdout and stderr concurrently, retain kill-on-drop behavior on cancellation, and keep output pipes open until the child exits.

## Testing

Add regression tests for fork-free sandboxed reads, writes, and file descriptor transfers; sandbox denial of outside paths and symlink escapes; descriptor isolation; bidirectional socket stdin; custom `argv[0]`; executable-format errors; and output-pipe lifetimes.

GitOrigin-RevId: d49c00787f30ec0bc196f9e066a0770fc8151152
2026-09-19 15:15:25 +00:00
Charlie Marsh 3801fc8dea Make local child process launch settings explicit (#46660)
## Why

The native macOS backend cannot inspect every setting or callback on a Tokio command. A shared, constrained launch API makes the supported settings explicit for both backends.

## What changed

- Replace `spawn_child` with `codex_utils_pty::Command`, enforcing an explicitly supplied environment, piped stdio, and kill-on-drop behavior.
- Add `ProcessMode::Inherit` and `ProcessMode::NewGroup`, honoring the selected mode in native macOS and Tokio spawning.
- Share the `Child` wrapper across platforms and migrate local MCP server launching to the new API, retaining its new process group and Windows suspended-spawn support.

## Testing

Adapt the existing macOS spawn compatibility and child lifecycle tests to the new API. Add a regression test that checks inherited and new process groups with both backends.

GitOrigin-RevId: 3e7a401659e3a8a94a13c4ff58d67bdcd2eea33d
2026-09-19 15:14:22 +00:00