Repository navigation
test(codex): bound Windows shell shim spawns inside the spawn budget #6862
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -42,6 +42,13 @@ const python3Path = process.platform === "win32" | |
| setCodexShimProbeObservationMsForTests(20); | ||
| afterAll(() => setCodexShimProbeObservationMsForTests(null)); | ||
| const psPath = process.platform !== "win32" && existsSync("/bin/ps") ? "/bin/ps" : ""; | ||
| // A loaded windows-latest runner starts cmd.exe and pwsh.exe past INTERNAL_DEADLINE_MS | ||
| // (a caller-token restore returned status null at 17.2s; the aged-lock holder has taken | ||
| // 8–19s to write its ready file). The shell is the assertion, so the bound stays inside | ||
| // SPAWN_BUDGET_MS and uses the same derivation as the other Windows spawn waits. | ||
| const SHELL_SPAWN_TIMEOUT_MS = process.platform === "win32" | ||
| ? SPAWN_BUDGET_MS - INTERNAL_DEADLINE_MS | ||
| : INTERNAL_DEADLINE_MS; | ||
|
|
||
| function successfulLauncher(label: string): string { | ||
| return process.platform === "win32" ? `${label}\r\n` : `#!/bin/sh\n# ${label}\nexit 0\n`; | ||
|
|
@@ -1177,8 +1184,8 @@ printf '%s\\n' child-codex | |
| }); | ||
| if (callerToken === undefined) delete env.OPENCODEX_API_AUTH_TOKEN; | ||
| const result = shell === "cmd" | ||
| ? spawnSync(process.env.ComSpec ?? "cmd.exe", ["/d", "/c", "driver.cmd"], { cwd: dir, env, encoding: "utf8", timeout: INTERNAL_DEADLINE_MS, windowsHide: true }) | ||
| : spawnSync(`${shell}.exe`, ["-NoProfile", "-NonInteractive", "-File", driverPath], { env, encoding: "utf8", timeout: INTERNAL_DEADLINE_MS, windowsHide: true }); | ||
| ? spawnSync(process.env.ComSpec ?? "cmd.exe", ["/d", "/c", "driver.cmd"], { cwd: dir, env, encoding: "utf8", timeout: SHELL_SPAWN_TIMEOUT_MS, windowsHide: true }) | ||
| : spawnSync(`${shell}.exe`, ["-NoProfile", "-NonInteractive", "-File", driverPath], { env, encoding: "utf8", timeout: SHELL_SPAWN_TIMEOUT_MS, windowsHide: true }); | ||
| expect(result.status, result.stderr).toBe(0); | ||
| expect(result.stdout.trim().split(/\r?\n/)).toEqual([ | ||
| `child:${callerToken || "file-token"}`, | ||
|
|
@@ -1220,7 +1227,7 @@ printf '%s\\n' child-codex | |
| const env = shimChildEnv({ OPENCODEX_HOME: dir, OPENCODEX_API_AUTH_TOKEN: callerToken ?? "", OCX_SHIM_BYPASS: "" }); | ||
| if (callerToken === undefined) delete env.OPENCODEX_API_AUTH_TOKEN; | ||
| const result = spawnSync(executable, ["-NoProfile", "-NonInteractive", "-File", driverPath], { | ||
| env, encoding: "utf8", timeout: INTERNAL_DEADLINE_MS, windowsHide: true, | ||
| env, encoding: "utf8", timeout: SHELL_SPAWN_TIMEOUT_MS, windowsHide: true, | ||
| }); | ||
| expect(result.error).toBeUndefined(); | ||
| expect(result.status, result.stderr).toBe(0); | ||
|
|
@@ -1236,7 +1243,7 @@ printf '%s\\n' child-codex | |
| // A failed process must complete, rather than satisfy the check through a timeout. | ||
| writeFileSync(driverPath, `\uFEFF$ErrorActionPreference = 'Stop'\n& '${wrapperPath.replace(/'/g, "''")}' exec\n`); | ||
| const uncaught = spawnSync(executable, ["-NoProfile", "-NonInteractive", "-File", driverPath], { | ||
| env, encoding: "utf8", timeout: INTERNAL_DEADLINE_MS, windowsHide: true, | ||
| env, encoding: "utf8", timeout: SHELL_SPAWN_TIMEOUT_MS, windowsHide: true, | ||
|
Comment on lines
1245
to
+1246
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
On a contended Windows runner, these two sequential Useful? React with 👍 / 👎. |
||
| }); | ||
| expect(uncaught.error).toBeUndefined(); | ||
| expect(uncaught.signal).toBeNull(); | ||
|
|
@@ -1755,14 +1762,15 @@ exit 127 | |
| stderr: "pipe", | ||
| }); | ||
| // Spawned holder child writing its ready marker: 8-19 s on windows-latest. | ||
| const deadline = Date.now() + INTERNAL_DEADLINE_MS; | ||
| const deadline = Date.now() + SHELL_SPAWN_TIMEOUT_MS; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: #!/bin/bash
set -euo pipefail
sed -n '1735,1785p' tests/codex-integration/codex-shim.test.ts
rg -n -C 3 'SPAWN_BUDGET_MS|test\(|it\(' tests/codex-integration/codex-shim.test.tsRepository: lidge-jun/opencodex Length of output: 29681 Use one deadline for both aged-lock waits. The ready-file poll and the sequential 🐛 Suggested fix const second = spawnSync(process.execPath, ["-e", secondScript], {
cwd: repoRoot(),
env: childEnv,
encoding: "utf8",
- timeout: SHELL_SPAWN_TIMEOUT_MS,
+ timeout: Math.max(1, deadline - Date.now()),
});🤖 Prompt for AI Agents |
||
| while (!existsSync(readyPath) && Date.now() < deadline) await Bun.sleep(5); | ||
| expect(existsSync(readyPath)).toBe(true); | ||
|
|
||
| const second = spawnSync(process.execPath, ["-e", secondScript], { | ||
| cwd: repoRoot(), | ||
| env: childEnv, | ||
| encoding: "utf8", | ||
| timeout: SHELL_SPAWN_TIMEOUT_MS, | ||
| }); | ||
| expect(second.status).toBe(0); | ||
| expect(JSON.parse(second.stdout.trim())).toEqual({ status: "deferred" }); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This alias is still derived from
INTERNAL_DEADLINE_MSand is passed to child-processtimeoutoptions, butDEADLINE_AS_SPAWN_TIMEOUTonly recognizes that token within 120 characters aftertimeout:. Consequently the alias makes this file disappear from the scan and permits its disposition to be removed, even though the aged-lock children dynamically importsrc/codex/shimand therefore exercise the repository-module cold-start class that the guard is intended to classify. Retain the disposition or extend the guard to resolve this named timeout instead of allowing the alias to bypass it.Useful? React with 👍 / 👎.