From 2cadb76d44b10146bb993d6fc8a755fc2e9da5b8 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 10 Aug 2026 15:43:14 +0200 Subject: [PATCH 1/2] [browser][coreCLR] corerun: hard-exit Node on explicit process exit 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/runtime#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(). Fixes dotnet/runtime#131937 --- src/coreclr/hosts/corerun/wasm/libCorerun.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/coreclr/hosts/corerun/wasm/libCorerun.js b/src/coreclr/hosts/corerun/wasm/libCorerun.js index e33003a0f35bff..82e299daca0b5e 100644 --- a/src/coreclr/hosts/corerun/wasm/libCorerun.js +++ b/src/coreclr/hosts/corerun/wasm/libCorerun.js @@ -32,6 +32,20 @@ function libCoreRunFactory() { } ENV["DOTNET_SYSTEM_GLOBALIZATION_INVARIANT"] = "true"; + + // Explicit exits (e.g. Environment.Exit) reach _proc_exit from deep inside managed code; letting + // Emscripten throw ExitStatus and unwind back through the live CLR interpreter frames runs native + // code after the runtime/FS teardown and aborts with the wrong exit code (https://github.com/dotnet/runtime/issues/131937). + // Under Node, end the process immediately with the requested code; stdio was already flushed by exitRuntime(). + if (ENVIRONMENT_IS_NODE) { + const original_proc_exit = _proc_exit; + _proc_exit = (code) => { + if (!keepRuntimeAlive()) { + process.exit(code); + } + return original_proc_exit(code); + }; + } }, }, $CORERUN__postset: "CORERUN.selfInitialize()", From 9be27453ea655eec49745a87e9776e73cb8d6612 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 10 Aug 2026 15:47:54 +0200 Subject: [PATCH 2/2] drop noise --- src/coreclr/hosts/corerun/wasm/libCorerun.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/coreclr/hosts/corerun/wasm/libCorerun.js b/src/coreclr/hosts/corerun/wasm/libCorerun.js index 82e299daca0b5e..510e9039b0e372 100644 --- a/src/coreclr/hosts/corerun/wasm/libCorerun.js +++ b/src/coreclr/hosts/corerun/wasm/libCorerun.js @@ -33,10 +33,6 @@ function libCoreRunFactory() { ENV["DOTNET_SYSTEM_GLOBALIZATION_INVARIANT"] = "true"; - // Explicit exits (e.g. Environment.Exit) reach _proc_exit from deep inside managed code; letting - // Emscripten throw ExitStatus and unwind back through the live CLR interpreter frames runs native - // code after the runtime/FS teardown and aborts with the wrong exit code (https://github.com/dotnet/runtime/issues/131937). - // Under Node, end the process immediately with the requested code; stdio was already flushed by exitRuntime(). if (ENVIRONMENT_IS_NODE) { const original_proc_exit = _proc_exit; _proc_exit = (code) => {