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
This commit is contained in:
Eric Traut
2026-09-29 04:38:37 +00:00
committed by copyberry
parent 3226512d47
commit fbc169827e
44 changed files with 380 additions and 71 deletions
@@ -72,7 +72,7 @@ async fn query_channel(wevtutil: &Path, channel: Channel) -> Option<Vec<Evidence
.map(|id| format!("EventID={id}"))
.collect::<Vec<_>>()
.join(" or ");
let mut child = Command::new(wevtutil)
let mut child = Command::from(codex_utils_process::background_command(wevtutil))
.args(["qe", channel.1])
.arg(format!(
"/q:*[System[({events}) and TimeCreated[timediff(@SystemTime) <= 604800000]]]"
+1 -1
View File
@@ -236,7 +236,7 @@ async fn endpoint_products() -> EndpointInspection {
#[cfg(any(target_os = "macos", target_os = "windows"))]
async fn product_command(program: impl AsRef<OsStr>, args: &[&str]) -> Option<Output> {
let mut command = Command::new(program);
let mut command = Command::from(codex_utils_process::background_command(program));
command
.args(args)
.stdin(Stdio::null())