Copilot CLI crashes on exit (Windows) — libuv `uv_async_send` on a closing handle (FAST_FAIL_FATAL_APP_EXIT)
Personne n'a encore pris cette issue.
- Langage dominant
- Shell
- Étoiles
- 11.2k
- Forks
- 1.9k
- Merge moyen
- 14 h 16 min
- PR mergées (30 j)
- 6
Description
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
- Launch
copiloton Windows x64. - Use it normally (any session involving network/async activity).
- Exit the CLI.
- 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_EXITFAILURE_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 settingprocess.exitCodeand 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.
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Piste de recherche
Commencez par suivre le Node DefaultProcessExitHandler et l’arrêt de la plateforme V8 décrits dans le rapport, en vous concentrant sur le chemin de process.exit et sur le uv_async_t de flush-tasks par isolate. Reproduisez le crash à la sortie sous Windows x64 et comparez le comportement du Node v24.16.0 inclus avec l’issue de suivi upstream nodejs/node#56645. Le travail est terminé lorsque copilot se termine proprement avec le code 0 et qu’aucun crash fail-fast ou WER ne se produit.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- node.js
- Domaine
- cli
- Type d'issue
- Bug
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Activité
- Calme
- Clarté
- Plutôt claire
- Accessibilité débutants
- 48/100