Skip to content

Commit a5dba82

Browse files
committed
process: Add exitCode property
This allows one to set a specific status code, while still letting the process exit gracefully once all async operations are completed.
1 parent b89b97d commit a5dba82

4 files changed

Lines changed: 100 additions & 3 deletions

File tree

doc/api/process.markdown

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,16 @@ To exit with a 'failure' code:
233233
The shell that executed node should see the exit code as 1.
234234

235235

236+
## process.exitCode
237+
238+
A number which will be the process exit code, when the process either
239+
exits gracefully, or is exited via `process.exit()` without specifying
240+
a code.
241+
242+
Specifying a code to `process.exit(code)` will override any previous
243+
setting of `process.exitCode`.
244+
245+
236246
## process.getgid()
237247

238248
Note: this function is only available on POSIX platforms (i.e. not Windows,

src/node.cc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3168,11 +3168,17 @@ void EmitExit(Environment* env) {
31683168
Local<Object> process_object = env->process_object();
31693169
process_object->Set(FIXED_ONE_BYTE_STRING(node_isolate, "_exiting"),
31703170
True(node_isolate));
3171+
3172+
Handle<String> exitCode = FIXED_ONE_BYTE_STRING(node_isolate, "exitCode");
3173+
int code = process_object->Get(exitCode)->IntegerValue();
3174+
31713175
Local<Value> args[] = {
31723176
FIXED_ONE_BYTE_STRING(node_isolate, "exit"),
3173-
Integer::New(0, node_isolate)
3177+
Integer::New(code, node_isolate)
31743178
};
3179+
31753180
MakeCallback(env, process_object, "emit", ARRAY_SIZE(args), args);
3181+
exit(code);
31763182
}
31773183

31783184

src/node.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,12 +545,16 @@
545545
};
546546

547547
startup.processKillAndExit = function() {
548+
process.exitCode = 0;
548549
process.exit = function(code) {
550+
if (NativeModule.require('util').isNumber(code))
551+
process.exitCode = code;
552+
549553
if (!process._exiting) {
550554
process._exiting = true;
551-
process.emit('exit', code || 0);
555+
process.emit('exit', process.exitCode || 0);
552556
}
553-
process.reallyExit(code || 0);
557+
process.reallyExit(process.exitCode || 0);
554558
};
555559

556560
process.kill = function(pid, sig) {
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright Joyent, Inc. and other Node contributors.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a
4+
// copy of this software and associated documentation files (the
5+
// "Software"), to deal in the Software without restriction, including
6+
// without limitation the rights to use, copy, modify, merge, publish,
7+
// distribute, sublicense, and/or sell copies of the Software, and to permit
8+
// persons to whom the Software is furnished to do so, subject to the
9+
// following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included
12+
// in all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17+
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18+
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20+
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
22+
var common = require('../common');
23+
var assert = require('assert');
24+
25+
switch (process.argv[2]) {
26+
case 'child1':
27+
return child1();
28+
case 'child2':
29+
return child2();
30+
case 'child3':
31+
return child3();
32+
case undefined:
33+
return parent();
34+
default:
35+
throw new Error('wtf');
36+
}
37+
38+
function child1() {
39+
process.exitCode = 42;
40+
process.on('exit', function(code) {
41+
assert.equal(code, 42);
42+
});
43+
}
44+
45+
function child2() {
46+
process.exitCode = 99;
47+
process.on('exit', function(code) {
48+
assert.equal(code, 42);
49+
});
50+
process.exit(42);
51+
}
52+
53+
function child3() {
54+
process.exitCode = 99;
55+
process.on('exit', function(code) {
56+
assert.equal(code, 0);
57+
});
58+
process.exit(0);
59+
}
60+
61+
function parent() {
62+
test('child1', 42);
63+
test('child2', 42);
64+
test('child3', 0);
65+
}
66+
67+
function test(arg, exit) {
68+
var spawn = require('child_process').spawn;
69+
var node = process.execPath;
70+
var f = __filename;
71+
spawn(node, [f, arg], {stdio: 'inherit'}).on('exit', function(code) {
72+
assert.equal(code, exit, 'wrong exit for ' +
73+
arg + '\nexpected:' + exit +
74+
' but got:' + code);
75+
console.log('ok - %s exited with %d', arg, exit);
76+
});
77+
}

0 commit comments

Comments
 (0)