Copilot CLI crashes on exit (Windows) — libuv `uv_async_send` on a closing handle (FAST_FAIL_FATAL_APP_EXIT)
- Ngôn ngữ chính
- Shell
- Star
- 11.2k
- Fork
- 1.9k
- Merge trung bình
- 14 giờ 16 phút
- Pull request đã merge (30 ngày)
- 6
Mô tả
### 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.
Hướng dẫn đóng góp
Hướng nghiên cứu
Bắt đầu bằng cách lần theo Node DefaultProcessExitHandler và quá trình tắt nền tảng V8 được mô tả trong báo cáo, tập trung vào đường đi của process.exit và uv_async_t flush-tasks theo từng isolate. Tái hiện sự cố crash khi thoát trên Windows x64 và so sánh hành vi của Node v24.16.0 được đóng gói với issue theo dõi upstream nodejs/node#56645. Được xem là hoàn tất khi copilot thoát sạch với code 0 và không có crash fail-fast hoặc WER.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- node.js
- Lĩnh vực
- cli
- Loại issue
- Lỗi
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức độ hoạt động
- Ít trao đổi
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 48/100