Uh oh!
There was an error while loading. Please reload this page.
[browser][coreCLR] corerun: hard-exit Node on explicit process exit (#131937) - #132078
Merged
pavelsavara merged 2 commits intoAug 10, 2026
Merged
Conversation
Environment.Exit reaches _proc_exit from deep inside interpreted managed code. Letting Emscripten throw ExitStatus and unwind back through the live CLR interpreter frames runs native code (a checked-build Frame::Pop assert, stdio) after the runtime/FS teardown, aborting with 'strerror called after runtime exit' and turning the intended exit code into 1 (dotnet#131937). Under Node, intercept _proc_exit and process.exit(code) immediately when the runtime is not kept alive, avoiding the unwind. stdio was already flushed by exitRuntime(). Fixesdotnet#131937
|
Azure Pipelines: Successfully started running 3 pipeline(s). 13 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
Contributor
Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara |
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes a browser-wasm CoreCLR checked-leg test failure where Environment.Exit(...) triggers an Emscripten ExitStatus throw that unwinds through live interpreter frames and aborts with the wrong exit code under Node.
Changes:
- Under Node, intercept
_proc_exitto hard-exit viaprocess.exit(code)when the runtime is not being kept alive. - Preserve existing behavior for non-Node environments and for keepalive/async scenarios by delegating to the original
_proc_exit.
Uh oh!
There was an error while loading. Please reload this page.
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (1)
src/coreclr/hosts/corerun/wasm/libCorerun.js:43
- Local variable
original_proc_exituses snake_case, which is inconsistent with the surrounding camelCase naming in this file. Consider renaming tooriginalProcExitwhile keeping the Emscripten-provided_proc_exitidentifier as-is.
const original_proc_exit = _proc_exit;
_proc_exit = (code) => {
if (!keepRuntimeAlive()) {
process.exit(code);
}
return original_proc_exit(code);
};
maraf
approved these changes
Aug 10, 2026
Uh oh!
There was an error while loading. Please reload this page.
jtschuster pushed a commit
to jtschuster/runtime
that referenced
this pull request
Aug 11, 2026
radekdoulik added a commit
to radekdoulik/runtime
that referenced
this pull request
Aug 18, 2026
Remove the b65423 and fieldlayout suppressions now that dotnet#132078 and dotnet#132172 fix their underlying CoreCLR browser failures. Retain the EventPipe, ContextualReflection, and Server GC exclusions that remain necessary on current main. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 808c6867-a1ea-4256-a003-46c17785ad04
radekdoulik added a commit
that referenced
this pull request
Aug 19, 2026
) ## Summary - Gate exactly four EventPipe events-validation projects on CoreCLR browser because they use unsupported `Process.GetCurrentProcess` and Process/PID-based managed self-process `DiagnosticsClient` collection; browser diagnostics use JS/WebSocket clients instead. - Temporarily suppress the CoreCLR-browser `ContextualReflection` interpreter failure through its tracked #131925 ActiveIssue. - Clarify that Server GC is disabled on CoreCLR browser by design. - `b65423` and `readytorun/fieldlayout` are absent from this change: current main includes the underlying fixes from #132078 and #132172, and both restored tests now pass targeted browser validation. Related issues: #131321, #131898, #131925. ## Validation - Merged and validated current `origin/main` at `663c457b86ccd35743374676a69de5ed97bc3b14`; the Checked browser `clr+libs` baseline passed with 0 warnings and 0 errors. - `b65423` passed 3/3: browser default, browser `DOTNET_TieredCompilation=0`, and native macOS arm64 process-isolated execution, each with expected/actual exit code 100. - `fieldlayout` passed 2/2 in browser default and no-tiered modes after producing and loading its composite Crossgen2/R2R WASM image. - Removing the ContextualReflection ActiveIssue reproduced #131925 in 2/2 browser modes; the final gated browser runs passed 2/2, and native ContextualReflection executed successfully. - An ungated no-tiered `GCEvents` run reproduced the expected `Process.GetCurrentProcess` PlatformNotSupportedException; all four final EventPipe projects were gated from CoreCLR-browser builds. - 14/14 representative property evaluations matched the intended scope across CoreCLR browser, CoreCLR macOS, and browser Mono. - Final delta: exactly 6 files, 23 insertions, 3 deletions. `git diff --check origin/main..HEAD` passed. > [!NOTE] > This pull request description was generated by GitHub Copilot. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 808c6867-a1ea-4256-a003-46c17785ad04
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b65423fails on thebrowser-wasmCoreCLR checked leg (#131937). The test catches its expectedTypeLoadException(the intendedExpected: 100), but the wasm runtime then aborts during shutdown:Root cause
The test ends with
Environment.Exit(100). On browser-wasm that goesEnvironment_Exit→ForceEEShutdown→EEPolicy::HandleExitProcess→SafeExitProcess→ExitProcess→PROCEndProcess→ Emscriptenexit()(the host links-sEXIT_RUNTIME=1).Emscripten's
exitJSrunsexitRuntime()— tearing down the EmscriptenFS/TTYand settingruntimeExited=true— then_proc_exitthrows theExitStatusJS exception. That exception unwinds up through the still-live CLR interpreter frames (wasm EH). During the unwind,Frame::Pop(Thread*)callsThread::GetFrame(), whose checked-only_ASSERTE(curSP <= m_pFrame && m_pFrame < m_CacheStackBase) fails because we are exiting mid-interpretation. The assert'sfprintf(stderr, ...)then hits musl stdio →fd_write→ the FS streams are already gone →getStreamCheckedthrowsErrnoError, and building its message callsstrerror, tripping Emscripten'sassert(!runtimeExited)→abort(). The abort turns the intended exit code 100 into 1.This only reproduces on the checked leg because the triggering
GetFrame()assert exists only under_DEBUG_IMPL.Fix
In the corerun wasm glue, under Node, intercept
_proc_exitand end the process immediately withprocess.exit(code)when the runtime is not kept alive — avoiding theExitStatusthrow and the unwind through live CLR frames.stdiowas already flushed byexitRuntime()before_proc_exitis reached. The browser/keepalive/onExitpath is untouched (Node-gated), and when the runtime is kept alive for async work it falls through to the original behavior._proc_exitis the correct interception point:wasmImports.exitbinds the originalexitJSby value (so reassigningexitJSwould miss the wasm-initiatedEnvironment.Exit), butexitJS's body calls_proc_exitby variable reference at call time.Validation
Ran the assembled
b65423.dllundercorerun.jsin Node, exactly as CI does:strerrorabort — matches the issue)Regression checks also pass: normal
return 7fromMain→ exit 7;Environment.Exit(0)→ exit 0.Fixes#131937
Note
This PR description was generated with the assistance of GitHub Copilot.