diff options
author | Matthew Francis Brunetti <zenflow87@gmail.com> | 2020-09-27 15:00:07 -0400 |
---|---|---|
committer | Gireesh Punathil <gpunathi@in.ibm.com> | 2020-10-28 12:32:50 +0530 |
commit | 3df5afb367cf6ae4b6309ad54e1a9cb2e6884d27 (patch) | |
tree | 0a7f774b50476150044687800954bad4c903f83f | |
parent | 923f76d5231256e69985e1bd897fd490ea0cbe9c (diff) | |
download | node-new-3df5afb367cf6ae4b6309ad54e1a9cb2e6884d27.tar.gz |
child_process: add ChildProcess 'spawn' event
The new event signals that the subprocess has spawned successfully and
no 'error' event will be emitted from failing to spawn.
Fixes: https://github.com/nodejs/node/issues/35288
PR-URL: https://github.com/nodejs/node/pull/35369
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
-rw-r--r-- | doc/api/child_process.md | 15 | ||||
-rw-r--r-- | lib/internal/child_process.js | 7 | ||||
-rw-r--r-- | test/parallel/test-child-process-spawn-error.js | 2 | ||||
-rw-r--r-- | test/parallel/test-child-process-spawn-event.js | 27 |
4 files changed, 51 insertions, 0 deletions
diff --git a/doc/api/child_process.md b/doc/api/child_process.md index bfe7850ad0..0f78ba9d44 100644 --- a/doc/api/child_process.md +++ b/doc/api/child_process.md @@ -1036,6 +1036,21 @@ child process, the `message` argument can contain data that JSON is not able to represent. See [Advanced serialization][] for more details. +### Event: `'spawn'` +<!-- YAML +added: REPLACEME +--> + +The `'spawn'` event is emitted once the child process has spawned successfully. + +If emitted, the `'spawn'` event comes before all other events and before any +data is received via `stdout` or `stderr`. + +The `'spawn'` event will fire regardless of whether an error occurs **within** +the spawned process. For example, if `bash some-command` spawns successfully, +the `'spawn'` event will fire, though `bash` may fail to spawn `some-command`. +This caveat also applies when using `{ shell: true }`. + ### `subprocess.channel` <!-- YAML added: v7.1.0 diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js index 092922f956..76e67317b9 100644 --- a/lib/internal/child_process.js +++ b/lib/internal/child_process.js @@ -401,6 +401,8 @@ ChildProcess.prototype.spawn = function(options) { this._handle.close(); this._handle = null; throw errnoException(err, 'spawn'); + } else { + process.nextTick(onSpawnNT, this); } this.pid = this._handle.pid; @@ -466,6 +468,11 @@ function onErrorNT(self, err) { } +function onSpawnNT(self) { + self.emit('spawn'); +} + + ChildProcess.prototype.kill = function(sig) { const signal = sig === 0 ? sig : diff --git a/test/parallel/test-child-process-spawn-error.js b/test/parallel/test-child-process-spawn-error.js index d6560ee9cc..a3464a505d 100644 --- a/test/parallel/test-child-process-spawn-error.js +++ b/test/parallel/test-child-process-spawn-error.js @@ -41,6 +41,8 @@ assert.strictEqual(enoentChild.stdio[0], enoentChild.stdin); assert.strictEqual(enoentChild.stdio[1], enoentChild.stdout); assert.strictEqual(enoentChild.stdio[2], enoentChild.stderr); +enoentChild.on('spawn', common.mustNotCall()); + enoentChild.on('error', common.mustCall(function(err) { assert.strictEqual(err.code, 'ENOENT'); assert.strictEqual(getSystemErrorName(err.errno), 'ENOENT'); diff --git a/test/parallel/test-child-process-spawn-event.js b/test/parallel/test-child-process-spawn-event.js new file mode 100644 index 0000000000..c025d86286 --- /dev/null +++ b/test/parallel/test-child-process-spawn-event.js @@ -0,0 +1,27 @@ +'use strict'; +const common = require('../common'); +const spawn = require('child_process').spawn; +const assert = require('assert'); + +const subprocess = spawn('echo', ['ok']); + +let didSpawn = false; +subprocess.on('spawn', function() { + didSpawn = true; +}); +function mustCallAfterSpawn() { + return common.mustCall(function() { + assert.ok(didSpawn); + }); +} + +subprocess.on('error', common.mustNotCall()); +subprocess.on('spawn', common.mustCall()); +subprocess.stdout.on('data', mustCallAfterSpawn()); +subprocess.stdout.on('end', mustCallAfterSpawn()); +subprocess.stdout.on('close', mustCallAfterSpawn()); +subprocess.stderr.on('data', common.mustNotCall()); +subprocess.stderr.on('end', mustCallAfterSpawn()); +subprocess.stderr.on('close', mustCallAfterSpawn()); +subprocess.on('exit', mustCallAfterSpawn()); +subprocess.on('close', mustCallAfterSpawn()); |