Copilot CLI crashes on exit (Windows) — libuv `uv_async_send` on a closing handle (FAST_FAIL_FATAL_APP_EXIT)
- 主要言語
- Shell
- スター
- 11.2k
- フォーク
- 1.9k
- 平均マージ
- 14時間 16分
- マージ済み PR(30日)
- 6
説明
### Describe the bug
On Windows x64, `copilot.exe` **consistently crashes at process exit** with a fatal
fail-fast (`0xc0000409`, subcode `0x7 FAST_FAIL_FATAL_APP_EXIT`). The session's work
completes normally; the crash happens only during teardown.
Live-debugger analysis (WinDbg attached to the crashing process) shows this is the
well-known **Windows-only Node.js/libuv shutdown race** — `uv_async_send()` is called
on a `uv_async_t` whose `UV_HANDLE_CLOSING` flag is already set, tripping the libuv
assertion:
```
Assertion failed: !(handle->flags & UV_HANDLE_CLOSING), file src\win\async.c
```
which calls `abort()` → `__fastfail(FAST_FAIL_FATAL_APP_EXIT)`. The bundled Node
(v24.16.0) ships libuv with this assertion **enabled**, so the otherwise-benign
teardown race becomes a hard crash.
Upstream tracking issue: https://github.com/nodejs/node/issues/56645
(Node 23/24/25 lines on Windows; Linux/macOS unaffected.)
### Affected version
- **GitHub Copilot CLI:** 1.0.74-0 (crash first captured on 1.0.73.0; reproduces on 1.0.74-0) - **Bundled Node.js:** v24.16.0 (win-x64, single-executable build), ICU 78 - **OS:** Windows x64 (build 10.0.29635) - **Onset:** started ~1 month ago (consistent with a CLI update that bumped the bundled Node)
### Steps to reproduce the behavior
1. Launch `copilot` on Windows x64.
2. Use it normally (any session involving network/async activity).
3. Exit the CLI.
4. The process aborts on exit with a fail-fast crash / WER entry (exit is not clean).
Reproduces every time on the affected machine.
### Expected behavior
The CLI should exit cleanly (exit code 0, no fail-fast/WER crash) after the session ends.
### Additional context
Two threads show both sides of the shutdown race:
**Crashing thread — "V8Worker" (a V8 background platform worker):**
```
copilot!uv_async_send+0x3a
→ _wassert("!(handle->flags & UV_HANDLE_CLOSING)", "src\win\async.c", 94)
→ abort()
→ __fastfail(FAST_FAIL_FATAL_APP_EXIT) ; int 29h, rcx=7
```
Disassembly of `uv_async_send` confirms the fatal branch is the top-of-function
guard (`test byte ptr [handle+0x58],1` / `UV_HANDLE_CLOSING`), not a failed
`PostQueuedCompletionStatus`.
**Main thread — in Node's process-exit teardown, joining workers:**
```
node::DefaultProcessExitHandler
→ (V8 platform shutdown)
→ uv_thread_join
→ WaitForSingleObjectEx ; waiting for the V8 worker to exit
```
So during `DefaultProcessExitHandler`, the main thread closes the per-isolate
"flush-tasks" `uv_async_t` (sets `UV_HANDLE_CLOSING`) and joins the V8 workers; a
V8 worker drains one last task and calls `uv_async_send()` on that now-closing
handle → assertion → abort.
`!analyze -v` summary:
- `ExceptionCode: c0000409` (STATUS_STACK_BUFFER_OVERRUN), `Subcode: 0x7 FAST_FAIL_FATAL_APP_EXIT`
- `FAILURE_BUCKET_ID: FAIL_FAST_FATAL_APP_EXIT_c0000409_copilot.exe!Unknown`
- Faulting thread is the V8 worker; instruction is `int 29h` (`__fastfail`).
## Suggested fixes (for maintainers)
- Avoid `process.exit()` during teardown when V8/libuv async handles are still
live; prefer setting `process.exitCode` and letting the loop drain, or add a
small deferral before forced exit (common community workaround for #56645).
- Ship a Node build with the libuv fix for nodejs/node#56645 once available, or a
Node line where the shutdown ordering doesn't hit this path on Windows.
- Impact is at-exit only (no data loss), but it produces a non-zero exit and a WER
crash entry on every exit, which is noisy and can break scripts that check the
CLI's exit code.
コントリビューションガイド
調査の方向性
まず、レポートで説明されている Node DefaultProcessExitHandler と V8 プラットフォームのシャットダウンを追跡し、process.exit のパスと per-isolate の flush-tasks uv_async_t に注目します。Windows x64 で終了時のクラッシュを再現し、バンドルされた Node v24.16.0 の動作を upstream の追跡 issue nodejs/node#56645 と比較します。copilot がコード 0 で正常に終了し、fail-fast または WER のクラッシュが発生しなければ完了です。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- node.js
- 領域
- cli
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 静か
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 48/100