Fix Windows in-process Node E2E cleanup hang#1983
Conversation
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 85a6b886-b234-446d-8719-8c7beb7ee03d
|
@roji Since this PR doesn't change any code that's specific to inproc mode, do you have a sense of whether there is a separate inproc cleanup issue? No objections to this PR doing more cleanup if it's helpful but want to check whether there was an inproc-specific issue that will likely remain. Or maybe this does interact with something specific to inproc but in a subtle way? |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Pull request overview
Makes Node E2E teardown bounded and deterministic, particularly for Windows in-process transport.
Changes:
- Adds timed client shutdown with force-stop fallback.
- Tracks and terminates the replay proxy child process.
Show a summary per file
| File | Description |
|---|---|
nodejs/test/e2e/harness/sdkTestContext.ts |
Adds Windows in-process cleanup fallback. |
nodejs/test/e2e/harness/CapiProxy.ts |
Adds bounded proxy shutdown and process termination. |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 2
- Review effort level: Medium
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 85a6b886-b234-446d-8719-8c7beb7ee03d
This comment has been minimized.
This comment has been minimized.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 85a6b886-b234-446d-8719-8c7beb7ee03d
|
@SteveSandersonMS There is an in-process-specific teardown angle here on Windows: in-process shutdown/disposal runs in the shared host process, so a stalled cleanup path is harder to recover from than stdio/tcp where we can just reap a child runtime process.\n\nThis PR also fixes a Windows process-tree issue in the proxy harness ( child on Windows can leave descendants alive unless we use ). Together these were the cleanup paths that matched the Windows in-process hang signature in CI. |
|
@SteveSandersonMS There is an in-process-specific teardown angle here on Windows: in-process shutdown/disposal runs in the shared host process, so a stalled cleanup path is harder to recover from than stdio/tcp where we can just reap a child runtime process.\n\nThis PR also fixes a Windows process-tree issue in the proxy harness (when launched through a shell on Windows, terminating only the parent can leave descendants alive unless we terminate the full tree). Together these matched the Windows in-process cleanup-hang signature in CI. |
Cross-SDK Consistency ReviewThis PR only modifies Node.js E2E test harness files ( The changes are internal test infrastructure improvements (deterministic proxy shutdown, Windows force-stop fallback), which are specific to the Node.js test setup. Equivalent concerns may exist in other language test harnesses but those are independent maintenance items, not API consistency gaps introduced by this PR. ✅ No cross-SDK consistency issues found.
|
|
@SteveSandersonMS Adding a bit more detail on the inproc-specificity. In stdio/tcp mode, the runtime is out-of-proc (separate child process), so teardown has a hard escape hatch: dispose transport and reap/kill the child if graceful shutdown stalls. In inprocess mode, runtime shutdown/disposal happens in the shared host process (the test worker itself), so if that path stalls there is no separate runtime process boundary to reap. That is why the force-stop fallback is scoped to Windows + inprocess, where this cleanup hang was observed. Separately, the proxy process-tree fix is Windows-general: when launched through a shell, killing only the parent can leave descendants alive unless we terminate the full tree. |
Yeah, IIUC the problem is that if there's a teardown stall in out-of-proc, it's not a big issue since we just kill the child process and move on. But with inproc we don't have that, so a stall causes a real hang in the main (only) process. So this is to make sure that we don't hang in inproc etc. I'll take a look at the root cause though. |
|
@SteveSandersonMS see #1984 for the root cause fix. This PR may still make sense to ensure we don't get long test hangs in the future, but I'm happy to close it (I'm not 100%, but doing this may actually partially mask such hangs in the future). |
|
Cool, happy either way whether you want to merge this change or #1984. |
Summary
CapiProxyand make shutdown deterministic (bounded/stoprequest + process-exit wait + forced kill fallback)afterAllteardown deadlocks insession.e2e.test.tsValidation
cd nodejs && COPILOT_SDK_DEFAULT_CONNECTION=inprocess npm test -- test/e2e/session.e2e.test.ts@github/copilot@1.0.71-0not accessible from packagefeedproxy)