openai / openai/codex-plugin-cc
Fix taskkill cancellation on Windows Git Bash (MSYS path mangling + non-English locale)
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 33.3k
- Forks
- 2.3k
- PR merge metrics
- No merged PRs in 30d
Description
Summary
/codex:cancel fails to terminate background jobs on Windows when Claude
Code runs under Git Bash (MSYS2), especially with a non-English system locale
(e.g. Korean CP949). Two independent bugs in scripts/lib/process.mjs
terminateProcessTree() combine to leave jobs stuck in the running state
forever.
Environment
- OS: Windows 11
- Shell: Git Bash (MSYS2), invoked via
spawnSync(..., { shell: process.env.SHELL }) - System locale: ko-KR (CP949)
- Plugin:
openai-codex(codex 1.0.3) inside Claude Code
Repro
/codex:rescue --background ...to spawn a background task/codex:cancel <job-id>
Observed error:
taskkill /PID 19712 /T /F: exit=1:
오류: 잘못된 인수/옵션 - 'C:/Program Files/Git/PID'.
The job's JSON on disk stays "status": "running" forever because cancel
throws before updating the registry.
Root cause
Bug 1 — MSYS argument path conversion
runCommand() passes shell: process.env.SHELL on win32. When the shell
is Git Bash's sh.exe, MSYS2 rewrites any argument that looks like a POSIX
path (/PID, /T, /F) into a Windows path prefixed with the MSYS root, e.g.
C:/Program Files/Git/PID. taskkill then rejects the mangled switch.
Bug 2 — English-only "missing process" detection
Even when taskkill succeeds in reporting that the PID is already gone, on
non-English Windows it prints the message in the system code page (CP949
for Korean) with an exit code of 128. looksLikeMissingProcessMessage() only
matches English phrases, so the "already dead" case is misclassified as a
hard failure, terminateProcessTree throws, and the cancel command never
updates the job status file.
Fix
--- a/scripts/lib/process.mjs
+++ b/scripts/lib/process.mjs
@@ -64,13 +64,18 @@ export function terminateProcessTree(pid, options = {})
{
if (platform === "win32") {
const result = runCommandImpl("taskkill", ["/PID", String(pid), "/T",
"/F"], {
cwd: options.cwd,
- env: options.env
+ env: {
+ ...(options.env ?? process.env),
+ MSYS_NO_PATHCONV: "1",
+ MSYS2_ARG_CONV_EXCL: "*"
+ }
});
if (!result.error && result.status === 0) {
return { attempted: true, delivered: true, method: "taskkill",
result };
}
const combinedOutput = `${result.stderr}\n${result.stdout}`.trim();
- if (!result.error && looksLikeMissingProcessMessage(combinedOutput)) {
+ if (!result.error && (result.status === 128 ||
looksLikeMissingProcessMessage(combinedOutput))) {
return { attempted: true, delivered: false, method: "taskkill",
result };
}
- MSYS_NO_PATHCONV=1 / MSYS2_ARG_CONV_EXCL='*' disable MSYS's argument
path rewriting just for this one child process. Any MSYS-based shell
(Git Bash, MSYS2, Cygwin-derived) honors at least one of these. - result.status === 128 is taskkill's locale-independent signal for
"process not found", which is exactly the state we want to treat as a
successful no-op during cancel.
Verification
Reproduced on Windows 11 / ko-KR / Git Bash. Before the patch: cancel
throws and the job JSON stays "status":"running". After the patch: cancel returns
Cancelled and the JSON transitions to "status":"cancelled" with
phase:"cancelled" and a cancelledAt timestamp, even when the underlying
PID was already gone.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in scripts/lib/process.mjs at terminateProcessTree() and inspect how runCommandImpl invokes taskkill on win32. Reproduce cancellation under Git Bash with a non-English locale, then verify that path switches are preserved, an already-missing PID is treated as a no-op, and the job JSON reaches cancelled state.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- bash, javascript
- Domain
- operating-systems, tooling
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100