From b7e4d5fc0e37b681b6efd8fabc2907ac9dd3f217 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Wed, 2 Sep 2020 14:41:04 +0200 Subject: [PATCH] src: shutdown libuv before exit() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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: https://github.com/nodejs/node/pull/35021 Reviewed-By: James M Snell Reviewed-By: Gus Caplan Reviewed-By: Santiago Gimeno Reviewed-By: Colin Ihrig Reviewed-By: Richard Lau Reviewed-By: David Carlier Reviewed-By: Zeyu Yang Reviewed-By: Gerhard Stöbich Reviewed-By: Juan José Arboleda Reviewed-By: Rich Trott --- src/api/environment.cc | 1 + .../test-crypto-op-during-process-exit.js | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 test/parallel/test-crypto-op-during-process-exit.js diff --git a/src/api/environment.cc b/src/api/environment.cc index a3090f3bf722ac..fa91ed8b404af4 100644 --- a/src/api/environment.cc +++ b/src/api/environment.cc @@ -714,6 +714,7 @@ ThreadId AllocateEnvironmentThreadId() { void DefaultProcessExitHandler(Environment* env, int exit_code) { Stop(env); DisposePlatform(); + uv_library_shutdown(); exit(exit_code); } diff --git a/test/parallel/test-crypto-op-during-process-exit.js b/test/parallel/test-crypto-op-during-process-exit.js new file mode 100644 index 00000000000000..a9a70c39e095a3 --- /dev/null +++ b/test/parallel/test-crypto-op-during-process-exit.js @@ -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));