Skip to content

Commit be525d7

Browse files
authored
src: consolidate exit codes in the code base
Add an ExitCode enum class and use it throughout the code base instead of hard-coding the exit codes everywhere. At the moment, the exit codes used in many places do not actually conform to what the documentation describes. With the new enums (which are also available to the JS land as constants in an internal binding) we could migrate to a more consistent usage of the codes, and eventually expose the constants to the user land when they are stable enough. PR-URL: #44746 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Jacob Smith <jacob@frende.me> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Darshan Sen <raisinten@gmail.com>
1 parent 66cedb4 commit be525d7

36 files changed

+379
-175
lines changed

lib/internal/async_hooks.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ const {
88
Symbol,
99
} = primordials;
1010

11+
const { exitCodes: { kGenericUserError } } = internalBinding('errors');
12+
1113
const promiseHooks = require('internal/promise_hooks');
1214

1315
const async_wrap = internalBinding('async_wrap');
@@ -171,7 +173,7 @@ function fatalError(e) {
171173
if (getOptionValue('--abort-on-uncaught-exception')) {
172174
process.abort();
173175
}
174-
process.exit(1);
176+
process.exit(kGenericUserError);
175177
}
176178

177179
function lookupPublicResource(resource) {

lib/internal/cluster/child.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ const EventEmitter = require('events');
1515
const { owner_symbol } = require('internal/async_hooks').symbols;
1616
const Worker = require('internal/cluster/worker');
1717
const { internal, sendHelper } = require('internal/cluster/utils');
18+
const { exitCodes: { kNoFailure } } = internalBinding('errors');
19+
1820
const cluster = new EventEmitter();
1921
const handles = new SafeMap();
2022
const indexes = new SafeMap();
@@ -43,7 +45,7 @@ cluster._setupWorker = function() {
4345
if (!worker.exitedAfterDisconnect) {
4446
// Unexpected disconnect, primary exited, or some such nastiness, so
4547
// worker exits immediately.
46-
process.exit(0);
48+
process.exit(kNoFailure);
4749
}
4850
});
4951

@@ -278,10 +280,10 @@ Worker.prototype.destroy = function() {
278280

279281
this.exitedAfterDisconnect = true;
280282
if (!this.isConnected()) {
281-
process.exit(0);
283+
process.exit(kNoFailure);
282284
} else {
283285
this.state = 'destroying';
284286
send({ act: 'exitedAfterDisconnect' }, () => process.disconnect());
285-
process.once('disconnect', () => process.exit(0));
287+
process.once('disconnect', () => process.exit(kNoFailure));
286288
}
287289
};

lib/internal/debugger/inspect.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ const { 0: InspectClient, 1: createRepl } =
4444
const debuglog = util.debuglog('inspect');
4545

4646
const { ERR_DEBUGGER_STARTUP_ERROR } = require('internal/errors').codes;
47+
const {
48+
exitCodes: {
49+
kGenericUserError,
50+
kNoFailure,
51+
},
52+
} = internalBinding('errors');
4753

4854
async function portIsFree(host, port, timeout = 3000) {
4955
if (port === 0) return; // Binding to a random port.
@@ -167,7 +173,7 @@ class NodeInspector {
167173

168174
// Handle all possible exits
169175
process.on('exit', () => this.killChild());
170-
const exitCodeZero = () => process.exit(0);
176+
const exitCodeZero = () => process.exit(kNoFailure);
171177
process.once('SIGTERM', exitCodeZero);
172178
process.once('SIGHUP', exitCodeZero);
173179

@@ -234,7 +240,7 @@ class NodeInspector {
234240
}
235241
}
236242
this.stdout.write(' failed to connect, please retry\n');
237-
process.exit(1);
243+
process.exit(kGenericUserError);
238244
}
239245

240246
clearLine() {
@@ -314,7 +320,7 @@ function parseArgv(args) {
314320
} catch (e) {
315321
if (e.code === 'ESRCH') {
316322
console.error(`Target process: ${pid} doesn't exist.`);
317-
process.exit(1);
323+
process.exit(kGenericUserError);
318324
}
319325
throw e;
320326
}
@@ -337,7 +343,8 @@ function startInspect(argv = ArrayPrototypeSlice(process.argv, 2),
337343
console.error(` ${invokedAs} <host>:<port>`);
338344
console.error(` ${invokedAs} --port=<port>`);
339345
console.error(` ${invokedAs} -p <pid>`);
340-
process.exit(1);
346+
// TODO(joyeecheung): should be kInvalidCommandLineArgument.
347+
process.exit(kGenericUserError);
341348
}
342349

343350
const options = parseArgv(argv);
@@ -355,7 +362,7 @@ function startInspect(argv = ArrayPrototypeSlice(process.argv, 2),
355362
console.error(e.message);
356363
}
357364
if (inspector.child) inspector.child.kill();
358-
process.exit(1);
365+
process.exit(kGenericUserError);
359366
}
360367

361368
process.on('uncaughtException', handleUnexpectedError);

lib/internal/main/repl.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ const console = require('internal/console/global');
1717

1818
const { getOptionValue } = require('internal/options');
1919

20+
const { exitCodes: { kGenericUserError } } = internalBinding('errors');
21+
2022
prepareMainThreadExecution();
2123

2224
markBootstrapComplete();
@@ -31,7 +33,8 @@ if (process.env.NODE_REPL_EXTERNAL_MODULE) {
3133
// If we can't write to stderr, we'd like to make this a noop,
3234
// so use console.error.
3335
console.error('Cannot specify --input-type for REPL');
34-
process.exit(1);
36+
// TODO(joyeecheung): should be kInvalidCommandLineArgument.
37+
process.exit(kGenericUserError);
3538
}
3639

3740
esmLoader.loadESM(() => {

lib/internal/main/test_runner.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const {
55
} = require('internal/process/pre_execution');
66
const { isUsingInspector } = require('internal/util/inspector');
77
const { run } = require('internal/test_runner/runner');
8+
const { exitCodes: { kGenericUserError } } = internalBinding('errors');
89

910
prepareMainThreadExecution(false);
1011
markBootstrapComplete();
@@ -22,5 +23,5 @@ if (isUsingInspector()) {
2223
const tapStream = run({ concurrency, inspectPort });
2324
tapStream.pipe(process.stdout);
2425
tapStream.once('test:fail', () => {
25-
process.exitCode = 1;
26+
process.exitCode = kGenericUserError;
2627
});

lib/internal/main/watch_mode.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ const {
1212
prepareMainThreadExecution,
1313
markBootstrapComplete
1414
} = require('internal/process/pre_execution');
15-
const { triggerUncaughtException } = internalBinding('errors');
15+
const {
16+
triggerUncaughtException,
17+
exitCodes: { kNoFailure },
18+
} = internalBinding('errors');
1619
const { getOptionValue } = require('internal/options');
1720
const { emitExperimentalWarning } = require('internal/util');
1821
const { FilesWatcher } = require('internal/watch_mode/files_watcher');
@@ -24,7 +27,6 @@ const { setTimeout, clearTimeout } = require('timers');
2427
const { resolve } = require('path');
2528
const { once, on } = require('events');
2629

27-
2830
prepareMainThreadExecution(false, false);
2931
markBootstrapComplete();
3032

@@ -125,7 +127,7 @@ function signalHandler(signal) {
125127
return async () => {
126128
watcher.clear();
127129
const exitCode = await killAndWait(signal, true);
128-
process.exit(exitCode ?? 0);
130+
process.exit(exitCode ?? kNoFailure);
129131
};
130132
}
131133
process.on('SIGTERM', signalHandler('SIGTERM'));

lib/internal/main/worker_thread.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ let debug = require('internal/util/debuglog').debuglog('worker', (fn) => {
6666
});
6767

6868
const assert = require('internal/assert');
69+
const { exitCodes: { kGenericUserError } } = internalBinding('errors');
6970

7071
patchProcessObject();
7172
setupInspectorHooks();
@@ -234,7 +235,7 @@ function workerOnGlobalUncaughtException(error, fromPromise) {
234235
if (!process._exiting) {
235236
try {
236237
process._exiting = true;
237-
process.exitCode = 1;
238+
process.exitCode = kGenericUserError;
238239
if (!handlerThrew) {
239240
process.emit('exit', process.exitCode);
240241
}

lib/internal/modules/esm/handle_process_exit.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
'use strict';
22

3+
const { exitCodes: { kUnfinishedTopLevelAwait } } = internalBinding('errors');
4+
35
// Handle a Promise from running code that potentially does Top-Level Await.
46
// In that case, it makes sense to set the exit code to a specific non-zero
57
// value if the main code never finishes running.
68
function handleProcessExit() {
7-
process.exitCode ??= 13;
9+
process.exitCode ??= kUnfinishedTopLevelAwait;
810
}
911

1012
module.exports = {

lib/internal/policy/manifest.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ const { getOptionValue } = require('internal/options');
4040
const shouldAbortOnUncaughtException = getOptionValue(
4141
'--abort-on-uncaught-exception'
4242
);
43+
const { exitCodes: { kGenericUserError } } = internalBinding('errors');
44+
4345
const { abort, exit, _rawDebug } = process;
4446
// #endregion
4547

@@ -72,7 +74,7 @@ function REACTION_EXIT(error) {
7274
if (shouldAbortOnUncaughtException) {
7375
abort();
7476
}
75-
exit(1);
77+
exit(kGenericUserError);
7678
}
7779

7880
function REACTION_LOG(error) {

lib/internal/process/execution.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const {
1414
ERR_EVAL_ESM_CANNOT_PRINT,
1515
},
1616
} = require('internal/errors');
17+
const { exitCodes: { kGenericUserError } } = internalBinding('errors');
1718

1819
const {
1920
executionAsyncId,
@@ -161,8 +162,8 @@ function createOnGlobalUncaughtException() {
161162
try {
162163
if (!process._exiting) {
163164
process._exiting = true;
164-
process.exitCode = 1;
165-
process.emit('exit', 1);
165+
process.exitCode = kGenericUserError;
166+
process.emit('exit', kGenericUserError);
166167
}
167168
} catch {
168169
// Nothing to be done about it at this point.

0 commit comments

Comments
 (0)