diff --git a/doc/api/process.markdown b/doc/api/process.markdown index 31a8f047452..1310a640753 100644 --- a/doc/api/process.markdown +++ b/doc/api/process.markdown @@ -233,6 +233,16 @@ To exit with a 'failure' code: The shell that executed node should see the exit code as 1. +## process.exitCode + +A number which will be the process exit code, when the process either +exits gracefully, or is exited via `process.exit()` without specifying +a code. + +Specifying a code to `process.exit(code)` will override any previous +setting of `process.exitCode`. + + ## process.getgid() Note: this function is only available on POSIX platforms (i.e. not Windows, diff --git a/src/node.cc b/src/node.cc index 4670151a8a3..0561f9d7de3 100644 --- a/src/node.cc +++ b/src/node.cc @@ -3168,11 +3168,17 @@ void EmitExit(Environment* env) { Local process_object = env->process_object(); process_object->Set(FIXED_ONE_BYTE_STRING(node_isolate, "_exiting"), True(node_isolate)); + + Handle exitCode = FIXED_ONE_BYTE_STRING(node_isolate, "exitCode"); + int code = process_object->Get(exitCode)->IntegerValue(); + Local args[] = { FIXED_ONE_BYTE_STRING(node_isolate, "exit"), - Integer::New(0, node_isolate) + Integer::New(code, node_isolate) }; + MakeCallback(env, process_object, "emit", ARRAY_SIZE(args), args); + exit(code); } diff --git a/src/node.js b/src/node.js index 9ba1b3b4a0f..0c24f7a54a0 100644 --- a/src/node.js +++ b/src/node.js @@ -545,12 +545,16 @@ }; startup.processKillAndExit = function() { + process.exitCode = 0; process.exit = function(code) { + if (NativeModule.require('util').isNumber(code)) + process.exitCode = code; + if (!process._exiting) { process._exiting = true; - process.emit('exit', code || 0); + process.emit('exit', process.exitCode || 0); } - process.reallyExit(code || 0); + process.reallyExit(process.exitCode || 0); }; process.kill = function(pid, sig) { diff --git a/test/simple/test-process-exit-code.js b/test/simple/test-process-exit-code.js new file mode 100644 index 00000000000..c7fc78e20f0 --- /dev/null +++ b/test/simple/test-process-exit-code.js @@ -0,0 +1,77 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var common = require('../common'); +var assert = require('assert'); + +switch (process.argv[2]) { + case 'child1': + return child1(); + case 'child2': + return child2(); + case 'child3': + return child3(); + case undefined: + return parent(); + default: + throw new Error('wtf'); +} + +function child1() { + process.exitCode = 42; + process.on('exit', function(code) { + assert.equal(code, 42); + }); +} + +function child2() { + process.exitCode = 99; + process.on('exit', function(code) { + assert.equal(code, 42); + }); + process.exit(42); +} + +function child3() { + process.exitCode = 99; + process.on('exit', function(code) { + assert.equal(code, 0); + }); + process.exit(0); +} + +function parent() { + test('child1', 42); + test('child2', 42); + test('child3', 0); +} + +function test(arg, exit) { + var spawn = require('child_process').spawn; + var node = process.execPath; + var f = __filename; + spawn(node, [f, arg], {stdio: 'inherit'}).on('exit', function(code) { + assert.equal(code, exit, 'wrong exit for ' + + arg + '\nexpected:' + exit + + ' but got:' + code); + console.log('ok - %s exited with %d', arg, exit); + }); +}