Skip to content

Commit

Permalink
src: shutdown libuv before exit()
Browse files Browse the repository at this point in the history
This ensures that no operations will be running on the libuv
threadpool, which is important because they may run into race
conditions with the global destructors being triggered from
`exit()`, such as in the added test example here.

PR-URL: #35021
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
Reviewed-By: Zeyu Yang <himself65@outlook.com>
Reviewed-By: Gerhard Stöbich <deb2001-github@yahoo.de>
Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
  • Loading branch information
addaleax authored and richardlau committed Sep 7, 2020
1 parent 28e89f6 commit f21d78d
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/api/environment.cc
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,7 @@ void DefaultProcessExitHandler(Environment* env, int exit_code) {
env->set_can_call_into_js(false);
env->stop_sub_worker_contexts();
DisposePlatform();
uv_library_shutdown();
exit(exit_code);
}

Expand Down
28 changes: 28 additions & 0 deletions test/parallel/test-crypto-op-during-process-exit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use strict';
const common = require('../common');
if (!common.hasCrypto) { common.skip('missing crypto'); }
const assert = require('assert');
const { generateKeyPair } = require('crypto');

if (common.isWindows) {
// Remove this conditional once the libuv change is in Node.js.
common.skip('crashing due to https://github.com/libuv/libuv/pull/2983');
}

// Regression test for a race condition: process.exit() might lead to OpenSSL
// cleaning up state from the exit() call via calling its destructor, but
// running OpenSSL operations on another thread might lead to them attempting
// to initialize OpenSSL, leading to a crash.
// This test crashed consistently on x64 Linux on Node v14.9.0.

generateKeyPair('rsa', {
modulusLength: 2048,
privateKeyEncoding: {
type: 'pkcs1',
format: 'pem'
}
}, (err/* , publicKey, privateKey */) => {
assert.ifError(err);
});

setTimeout(() => process.exit(), common.platformTimeout(10));

0 comments on commit f21d78d

Please sign in to comment.