feat(cli): --debug-cli reports active handles that block process exit#1651
feat(cli): --debug-cli reports active handles that block process exit#1651sai-ray wants to merge 12 commits into
--debug-cli reports active handles that block process exit#1651Conversation
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1651 +/- ##
==========================================
+ Coverage 88.98% 89.09% +0.10%
==========================================
Files 77 78 +1
Lines 11354 11734 +380
Branches 1591 1631 +40
==========================================
+ Hits 10103 10454 +351
- Misses 1221 1249 +28
- Partials 30 31 +1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
--debug-cli reports active handles that block process exit
|
Total lines changed 1252 is greater than 1000. Please consider breaking this PR down. |
Can you confirm this with a packaged CLI? Because we bundle all the source, and I'm pretty sure source locations are going to end up as I don't think we have to go to source maps (though we can), but we should at least have the trace of all functions. |
In the bundle the locations just came out as I'd like to get the actual file and line too and was curious how you'd approach it. From what I found, shipping a source map would do it since |
In some CI environments a
cdkcommand finishes its work but the process never exits, and the job hangs until the runner kills it (issue #1217). It's intermittent and environment-specific, so there's no way today to see what is keeping the process alive.This adds that visibility behind the existing
--debug-cliflag. If the process is still alive shortly after the work is done, the CLI prints the handles holding it open and where each was created. It's a diagnostic only and on a normal run nothing is printed.How it works
One module,
lib/cli/debug-handles.ts, built on Node'sasync_hooks.LeakedHandleTrackerwatches every async resource as it's created (recording its type and creation stack) and forgets it when it's cleaned up. At exit,report()lists the ones still keeping the process alive, skipping handles that were garbage collected or.unref()'d since those don't block exit.Wiring in
cli.tsis two lines: enable tracking at startup when--debug-cliis set, and schedule the report behind a short,.unref()'d grace timer:The grace timer is the key bit: a handle open the instant work finishes might just be closing on a clean shutdown. The timer lets the normal exit path finish first, and because it's
.unref()'d it never fires on a clean run. The report only shows up when the process is genuinely still alive after the window, which is likely the hang.What the user sees
Each entry shows the type, a plain-language description, the function it was created in, and the line of code (greyed). Handles opened entirely inside Node show
(no application stack frames), they're still listed so nothing is hidden.Tests
test/cli/debug-handles.test.tsuses real resources (only the IoHost is faked): a leaked timer and a real leaked TCP connection are reported,.unref()'d handles are excluded, and promise noise is filtered out.Checklist
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license