Commit Graph
12 Commits
Author SHA1 Message Date
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