#52856: fix: tear down Node's per-process state before the process exits
Description of Change
Since Node 24.9 (nodejs/node#59856), loading tls starts a background thread that parses the CA certificates. Upstream joins it in node::TearDownOncePerProcess(), but Electron never called that on any exit path, so a process that loads tls/https and exits soon after can have exit() destroy Node's static per_process::cli_options_mutex underneath that thread → uv_mutex_lock → abort(). Silent SIGABRT, no output. This is what has been picking off random test-tls-* / test-https-* tests in the nn-test job (3 of the last 34 runs). Fixes #52860.
NodeMain(ELECTRON_RUN_AS_NODE): callnode::TearDownOncePerProcess()afterV8::Dispose(), matchingnode::Start().NodeBindings: the instance that ranInitializeOncePerProcess()now runsTearDownOncePerProcess()in its destructor — covers normal browser quit and the utility process.Browser::ExitWithCode: the pre-readyapp.exit()path callsexit()directly with nothing torn down, so tear Node down first there too.- spec:
require('node:tls'); app.exit(123)before ready, 15×, asserting a clean exit.
Linux x64 testing build, this branch vs main:
| scenario | before | after |
|---|---|---|
require('node:tls'); app.exit() before ready (browser process) |
20/100 SIGABRT, 37/100 read destroyed statics | 0/700 |
ELECTRON_RUN_AS_NODE=1 electron -e "require('tls')" |
3/2,000 SIGABRT | 0/20,000 |
Node parallel/test-tls-* at -j128 |
3/96,000 (exitcode: -6, all three cores in LoadCACertificates → uv_mutex_lock → abort) |
0/48,000 |
Checklist
- PR description included and stakeholders cc'd
-
npm testpasses - tests are changed or added
- relevant API documentation, tutorials, and examples are updated and follow the documentation style guide
- PR release notes describe the change in a way relevant to app developers, and are capitalized, punctuated, and past tense.
Release Notes
Notes: Fixed a possible crash (SIGABRT) during process exit when the process had loaded tls/https shortly before exiting, affecting app.exit() before ready and short-lived ELECTRON_RUN_AS_NODE / child_process.fork() scripts.
Backports
Semver Impact
Semantic Versioning helps users understand the impact of updates:
- Major (X.y.z): Breaking changes that may require code modifications
- Minor (x.Y.z): New features that maintain backward compatibility
- Patch (x.y.Z): Bug fixes that don't change the API
- None: Changes that don't affect using facing parts of Electron