mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
worker: fix exit code for error thrown in handler
Change worker exit code when the unhandled exception handler throws from 0 to 7 fixes: https://github.com/nodejs/node/issues/37996 PR-URL: https://github.com/nodejs/node/pull/38012 Fixes: https://github.com/nodejs/node/issues/37996 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
committed by
James M Snell
parent
1e4a2bcbee
commit
6986fa07eb
@@ -199,10 +199,12 @@ port.on('message', (message) => {
|
||||
function workerOnGlobalUncaughtException(error, fromPromise) {
|
||||
debug(`[${threadId}] gets uncaught exception`);
|
||||
let handled = false;
|
||||
let handlerThrew = false;
|
||||
try {
|
||||
handled = onGlobalUncaughtException(error, fromPromise);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
handlerThrew = true;
|
||||
}
|
||||
debug(`[${threadId}] uncaught exception handled = ${handled}`);
|
||||
|
||||
@@ -210,6 +212,16 @@ function workerOnGlobalUncaughtException(error, fromPromise) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!process._exiting) {
|
||||
try {
|
||||
process._exiting = true;
|
||||
process.exitCode = 1;
|
||||
if (!handlerThrew) {
|
||||
process.emit('exit', process.exitCode);
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
let serialized;
|
||||
try {
|
||||
const { serializeError } = require('internal/error_serdes');
|
||||
|
||||
214
test/fixtures/process-exit-code-cases.js
vendored
214
test/fixtures/process-exit-code-cases.js
vendored
@@ -2,112 +2,126 @@
|
||||
|
||||
const assert = require('assert');
|
||||
|
||||
const cases = [];
|
||||
module.exports = cases;
|
||||
function getTestCases(isWorker = false) {
|
||||
const cases = [];
|
||||
function exitsOnExitCodeSet() {
|
||||
process.exitCode = 42;
|
||||
process.on('exit', (code) => {
|
||||
assert.strictEqual(process.exitCode, 42);
|
||||
assert.strictEqual(code, 42);
|
||||
});
|
||||
}
|
||||
cases.push({ func: exitsOnExitCodeSet, result: 42 });
|
||||
|
||||
function exitsOnExitCodeSet() {
|
||||
process.exitCode = 42;
|
||||
process.on('exit', (code) => {
|
||||
assert.strictEqual(process.exitCode, 42);
|
||||
assert.strictEqual(code, 42);
|
||||
});
|
||||
}
|
||||
cases.push({ func: exitsOnExitCodeSet, result: 42 });
|
||||
|
||||
function changesCodeViaExit() {
|
||||
process.exitCode = 99;
|
||||
process.on('exit', (code) => {
|
||||
assert.strictEqual(process.exitCode, 42);
|
||||
assert.strictEqual(code, 42);
|
||||
});
|
||||
process.exit(42);
|
||||
}
|
||||
cases.push({ func: changesCodeViaExit, result: 42 });
|
||||
|
||||
function changesCodeZeroExit() {
|
||||
process.exitCode = 99;
|
||||
process.on('exit', (code) => {
|
||||
assert.strictEqual(process.exitCode, 0);
|
||||
assert.strictEqual(code, 0);
|
||||
});
|
||||
process.exit(0);
|
||||
}
|
||||
cases.push({ func: changesCodeZeroExit, result: 0 });
|
||||
|
||||
function exitWithOneOnUncaught() {
|
||||
process.exitCode = 99;
|
||||
process.on('exit', (code) => {
|
||||
// cannot use assert because it will be uncaughtException -> 1 exit code
|
||||
// that will render this test useless
|
||||
if (code !== 1 || process.exitCode !== 1) {
|
||||
console.log('wrong code! expected 1 for uncaughtException');
|
||||
process.exit(99);
|
||||
}
|
||||
});
|
||||
throw new Error('ok');
|
||||
}
|
||||
cases.push({
|
||||
func: exitWithOneOnUncaught,
|
||||
result: 1,
|
||||
error: /^Error: ok$/,
|
||||
});
|
||||
|
||||
function changeCodeInsideExit() {
|
||||
process.exitCode = 95;
|
||||
process.on('exit', (code) => {
|
||||
assert.strictEqual(process.exitCode, 95);
|
||||
assert.strictEqual(code, 95);
|
||||
function changesCodeViaExit() {
|
||||
process.exitCode = 99;
|
||||
});
|
||||
}
|
||||
cases.push({ func: changeCodeInsideExit, result: 99 });
|
||||
process.on('exit', (code) => {
|
||||
assert.strictEqual(process.exitCode, 42);
|
||||
assert.strictEqual(code, 42);
|
||||
});
|
||||
process.exit(42);
|
||||
}
|
||||
cases.push({ func: changesCodeViaExit, result: 42 });
|
||||
|
||||
function zeroExitWithUncaughtHandler() {
|
||||
process.on('exit', (code) => {
|
||||
assert.strictEqual(process.exitCode, 0);
|
||||
assert.strictEqual(code, 0);
|
||||
});
|
||||
process.on('uncaughtException', () => {});
|
||||
throw new Error('ok');
|
||||
}
|
||||
cases.push({ func: zeroExitWithUncaughtHandler, result: 0 });
|
||||
function changesCodeZeroExit() {
|
||||
process.exitCode = 99;
|
||||
process.on('exit', (code) => {
|
||||
assert.strictEqual(process.exitCode, 0);
|
||||
assert.strictEqual(code, 0);
|
||||
});
|
||||
process.exit(0);
|
||||
}
|
||||
cases.push({ func: changesCodeZeroExit, result: 0 });
|
||||
|
||||
function changeCodeInUncaughtHandler() {
|
||||
process.on('exit', (code) => {
|
||||
assert.strictEqual(process.exitCode, 97);
|
||||
assert.strictEqual(code, 97);
|
||||
function exitWithOneOnUncaught() {
|
||||
process.exitCode = 99;
|
||||
process.on('exit', (code) => {
|
||||
// cannot use assert because it will be uncaughtException -> 1 exit code
|
||||
// that will render this test useless
|
||||
if (code !== 1 || process.exitCode !== 1) {
|
||||
console.log('wrong code! expected 1 for uncaughtException');
|
||||
process.exit(99);
|
||||
}
|
||||
});
|
||||
throw new Error('ok');
|
||||
}
|
||||
cases.push({
|
||||
func: exitWithOneOnUncaught,
|
||||
result: 1,
|
||||
error: /^Error: ok$/,
|
||||
});
|
||||
process.on('uncaughtException', () => {
|
||||
process.exitCode = 97;
|
||||
});
|
||||
throw new Error('ok');
|
||||
}
|
||||
cases.push({ func: changeCodeInUncaughtHandler, result: 97 });
|
||||
|
||||
function changeCodeInExitWithUncaught() {
|
||||
process.on('exit', (code) => {
|
||||
assert.strictEqual(process.exitCode, 1);
|
||||
assert.strictEqual(code, 1);
|
||||
process.exitCode = 98;
|
||||
});
|
||||
throw new Error('ok');
|
||||
}
|
||||
cases.push({
|
||||
func: changeCodeInExitWithUncaught,
|
||||
result: 98,
|
||||
error: /^Error: ok$/,
|
||||
});
|
||||
function changeCodeInsideExit() {
|
||||
process.exitCode = 95;
|
||||
process.on('exit', (code) => {
|
||||
assert.strictEqual(process.exitCode, 95);
|
||||
assert.strictEqual(code, 95);
|
||||
process.exitCode = 99;
|
||||
});
|
||||
}
|
||||
cases.push({ func: changeCodeInsideExit, result: 99 });
|
||||
|
||||
function exitWithZeroInExitWithUncaught() {
|
||||
process.on('exit', (code) => {
|
||||
assert.strictEqual(process.exitCode, 1);
|
||||
assert.strictEqual(code, 1);
|
||||
process.exitCode = 0;
|
||||
function zeroExitWithUncaughtHandler() {
|
||||
process.on('exit', (code) => {
|
||||
assert.strictEqual(process.exitCode, 0);
|
||||
assert.strictEqual(code, 0);
|
||||
});
|
||||
process.on('uncaughtException', () => { });
|
||||
throw new Error('ok');
|
||||
}
|
||||
cases.push({ func: zeroExitWithUncaughtHandler, result: 0 });
|
||||
|
||||
function changeCodeInUncaughtHandler() {
|
||||
process.on('exit', (code) => {
|
||||
assert.strictEqual(process.exitCode, 97);
|
||||
assert.strictEqual(code, 97);
|
||||
});
|
||||
process.on('uncaughtException', () => {
|
||||
process.exitCode = 97;
|
||||
});
|
||||
throw new Error('ok');
|
||||
}
|
||||
cases.push({ func: changeCodeInUncaughtHandler, result: 97 });
|
||||
|
||||
function changeCodeInExitWithUncaught() {
|
||||
process.on('exit', (code) => {
|
||||
assert.strictEqual(process.exitCode, 1);
|
||||
assert.strictEqual(code, 1);
|
||||
process.exitCode = 98;
|
||||
});
|
||||
throw new Error('ok');
|
||||
}
|
||||
cases.push({
|
||||
func: changeCodeInExitWithUncaught,
|
||||
result: 98,
|
||||
error: /^Error: ok$/,
|
||||
});
|
||||
throw new Error('ok');
|
||||
|
||||
function exitWithZeroInExitWithUncaught() {
|
||||
process.on('exit', (code) => {
|
||||
assert.strictEqual(process.exitCode, 1);
|
||||
assert.strictEqual(code, 1);
|
||||
process.exitCode = 0;
|
||||
});
|
||||
throw new Error('ok');
|
||||
}
|
||||
cases.push({
|
||||
func: exitWithZeroInExitWithUncaught,
|
||||
result: 0,
|
||||
error: /^Error: ok$/,
|
||||
});
|
||||
|
||||
function exitWithThrowInUncaughtHandler() {
|
||||
process.on('uncaughtException', () => {
|
||||
throw new Error('ok')
|
||||
});
|
||||
throw new Error('bad');
|
||||
}
|
||||
cases.push({
|
||||
func: exitWithThrowInUncaughtHandler,
|
||||
result: isWorker ? 1 : 7,
|
||||
error: /^Error: ok$/,
|
||||
});
|
||||
return cases;
|
||||
}
|
||||
cases.push({
|
||||
func: exitWithZeroInExitWithUncaught,
|
||||
result: 0,
|
||||
error: /^Error: ok$/,
|
||||
});
|
||||
exports.getTestCases = getTestCases;
|
||||
|
||||
@@ -24,7 +24,8 @@ require('../common');
|
||||
const assert = require('assert');
|
||||
const debug = require('util').debuglog('test');
|
||||
|
||||
const testCases = require('../fixtures/process-exit-code-cases');
|
||||
const { getTestCases } = require('../fixtures/process-exit-code-cases');
|
||||
const testCases = getTestCases(false);
|
||||
|
||||
if (!process.argv[2]) {
|
||||
parent();
|
||||
|
||||
@@ -8,7 +8,8 @@ const assert = require('assert');
|
||||
const worker = require('worker_threads');
|
||||
const { Worker, parentPort } = worker;
|
||||
|
||||
const testCases = require('../fixtures/process-exit-code-cases');
|
||||
const { getTestCases } = require('../fixtures/process-exit-code-cases');
|
||||
const testCases = getTestCases(true);
|
||||
|
||||
// Do not use isMainThread so that this test itself can be run inside a Worker.
|
||||
if (!process.env.HAS_STARTED_WORKER) {
|
||||
|
||||
Reference in New Issue
Block a user