From 292f433244c12d5d2b34d9b8e8d2e8e0e074d139 Mon Sep 17 00:00:00 2001 From: Jessica Quynh Tran Date: Sun, 30 Oct 2016 19:51:37 -0400 Subject: [PATCH 1/5] child_process: add detached option to .exec() To maintain consistency across child_process functions, the detached option has been added to the .exec(). This was noticed when the documentation was not explicit with using --detached in .execSync(). Both functions have also been documented in this commit. --- doc/api/child_process.md | 7 +++++++ lib/child_process.js | 1 + 2 files changed, 8 insertions(+) diff --git a/doc/api/child_process.md b/doc/api/child_process.md index 306f125f9841..4ab2cd104a10 100644 --- a/doc/api/child_process.md +++ b/doc/api/child_process.md @@ -137,6 +137,9 @@ added: v0.1.90 * `timeout` {Number} (Default: `0`) * [`maxBuffer`][] {Number} largest amount of data (in bytes) allowed on stdout or stderr - if exceeded child process is killed (Default: `200*1024`) + * `detached` {Boolean} Prepare child to run independently of its parent + process. Specific behavior depends on the platform, see + [`options.detached`][]) * `killSignal` {String} (Default: `'SIGTERM'`) * `uid` {Number} Sets the user identity of the process. (See setuid(2).) * `gid` {Number} Sets the group identity of the process. (See setgid(2).) @@ -183,6 +186,7 @@ the process is spawned. The default options are: encoding: 'utf8', timeout: 0, maxBuffer: 200*1024, + detached: false, killSignal: 'SIGTERM', cwd: null, env: null @@ -625,6 +629,9 @@ added: v0.11.12 * `gid` {Number} Sets the group identity of the process. (See setgid(2).) * `timeout` {Number} In milliseconds the maximum amount of time the process is allowed to run. (Default: `undefined`) + * `detached` {Boolean} Prepare child to run independently of its parent + process. Specific behavior depends on the platform, see + [`options.detached`][]) * `killSignal` {String} The signal value to be used when the spawned process will be killed. (Default: `'SIGTERM'`) * [`maxBuffer`][] {Number} largest amount of data (in bytes) allowed on diff --git a/lib/child_process.js b/lib/child_process.js index a7815ac85c3b..7b714fdbb1fa 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -151,6 +151,7 @@ exports.execFile = function(file /*, args, options, callback*/) { gid: options.gid, uid: options.uid, shell: options.shell, + detached: !!options.detached, windowsVerbatimArguments: !!options.windowsVerbatimArguments }); From cc7a6f9d9cc2d5289e1596c9cbe755f607821402 Mon Sep 17 00:00:00 2001 From: Jessica Quynh Tran Date: Wed, 2 Nov 2016 17:49:23 -0400 Subject: [PATCH 2/5] add similar test to .exec() function --- .../parent-process-exec-nonpersistent.js | 13 ++++++++++ .../test-child-process-exec-detached.js | 26 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 test/fixtures/parent-process-exec-nonpersistent.js create mode 100644 test/parallel/test-child-process-exec-detached.js diff --git a/test/fixtures/parent-process-exec-nonpersistent.js b/test/fixtures/parent-process-exec-nonpersistent.js new file mode 100644 index 000000000000..0f5099fc4ed1 --- /dev/null +++ b/test/fixtures/parent-process-exec-nonpersistent.js @@ -0,0 +1,13 @@ + +var execFile = require('child_process').execFile, + path = require('path'), + childPath = path.join(__dirname, 'child-process-persistent.js'); + +var child = execFile(process.execPath, [ childPath ], { + detached: true, + stdio: 'ignore' +}); + +console.log(child.pid); + +child.unref(); diff --git a/test/parallel/test-child-process-exec-detached.js b/test/parallel/test-child-process-exec-detached.js new file mode 100644 index 000000000000..d5fa165f6a7c --- /dev/null +++ b/test/parallel/test-child-process-exec-detached.js @@ -0,0 +1,26 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const path = require('path'); +const execFile = require('child_process').execFile; +const childPath = require.resolve(common.fixturesDir + '/parent-process-exec-nonpersistent.js'); + +var persistentPid = -1; + +const execParent = execFile(process.execPath, [ childPath], { + timeout: 1000 +}); + +execParent.stdout.on('data', function(data) { + persistentPid = data; +}); + +process.on('exit', () => { + assert.notStrictEqual(persistentPid, -1); + assert.throws(function(data) { + process.kill(execParent.pid); + }); + assert.doesNotThrow(function() { + process.kill(persistentPid); + }); +}); From 182727be91e3aa3aaaf417e99523d4ece5225e69 Mon Sep 17 00:00:00 2001 From: Jessica Quynh Tran Date: Wed, 2 Nov 2016 17:52:58 -0400 Subject: [PATCH 3/5] update doc --- doc/api/child_process.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/doc/api/child_process.md b/doc/api/child_process.md index 4ab2cd104a10..fce444ebc246 100644 --- a/doc/api/child_process.md +++ b/doc/api/child_process.md @@ -139,7 +139,7 @@ added: v0.1.90 stdout or stderr - if exceeded child process is killed (Default: `200*1024`) * `detached` {Boolean} Prepare child to run independently of its parent process. Specific behavior depends on the platform, see - [`options.detached`][]) + [`options.detached`][] * `killSignal` {String} (Default: `'SIGTERM'`) * `uid` {Number} Sets the user identity of the process. (See setuid(2).) * `gid` {Number} Sets the group identity of the process. (See setgid(2).) @@ -315,7 +315,7 @@ added: v0.1.90 [`options.stdio`][`stdio`]) * `detached` {Boolean} Prepare child to run independently of its parent process. Specific behavior depends on the platform, see - [`options.detached`][]) + [`options.detached`][] * `uid` {Number} Sets the user identity of the process. (See setuid(2).) * `gid` {Number} Sets the group identity of the process. (See setgid(2).) * `shell` {Boolean|String} If `true`, runs `command` inside of a shell. Uses @@ -587,6 +587,9 @@ added: v0.11.12 * `gid` {Number} Sets the group identity of the process. (See setgid(2).) * `timeout` {Number} In milliseconds the maximum amount of time the process is allowed to run. (Default: `undefined`) + * `detached` {Boolean} Prepare child to run independently of its parent + process. Specific behavior depends on the platform, see + [`options.detached`][] * `killSignal` {String} The signal value to be used when the spawned process will be killed. (Default: `'SIGTERM'`) * [`maxBuffer`][] {Number} largest amount of data (in bytes) allowed on @@ -631,7 +634,7 @@ added: v0.11.12 is allowed to run. (Default: `undefined`) * `detached` {Boolean} Prepare child to run independently of its parent process. Specific behavior depends on the platform, see - [`options.detached`][]) + [`options.detached`][] * `killSignal` {String} The signal value to be used when the spawned process will be killed. (Default: `'SIGTERM'`) * [`maxBuffer`][] {Number} largest amount of data (in bytes) allowed on From 23d09684c3c81b4b0643629d495dee0a29a370d8 Mon Sep 17 00:00:00 2001 From: Jessica Quynh Tran Date: Wed, 16 Nov 2016 00:07:41 -0500 Subject: [PATCH 4/5] implement cp.fork to recieve the PID of the detached child --- .../parent-process-exec-nonpersistent.js | 11 ++++---- .../test-child-process-exec-detached.js | 26 ++++++++----------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/test/fixtures/parent-process-exec-nonpersistent.js b/test/fixtures/parent-process-exec-nonpersistent.js index 0f5099fc4ed1..e62dd9ae4621 100644 --- a/test/fixtures/parent-process-exec-nonpersistent.js +++ b/test/fixtures/parent-process-exec-nonpersistent.js @@ -1,13 +1,14 @@ - -var execFile = require('child_process').execFile, - path = require('path'), - childPath = path.join(__dirname, 'child-process-persistent.js'); +'use strict'; +const execFile = require('child_process').execFile; +const path = require('path'); +const childPath = path.join(__dirname, 'child-process-persistent.js'); var child = execFile(process.execPath, [ childPath ], { detached: true, + timeout: 100, stdio: 'ignore' }); -console.log(child.pid); +process.send(child.pid); child.unref(); diff --git a/test/parallel/test-child-process-exec-detached.js b/test/parallel/test-child-process-exec-detached.js index d5fa165f6a7c..a3541adbd2f4 100644 --- a/test/parallel/test-child-process-exec-detached.js +++ b/test/parallel/test-child-process-exec-detached.js @@ -2,25 +2,21 @@ const common = require('../common'); const assert = require('assert'); const path = require('path'); -const execFile = require('child_process').execFile; -const childPath = require.resolve(common.fixturesDir + '/parent-process-exec-nonpersistent.js'); +const cp = require('child_process'); +const childPath = path.join(common.fixturesDir, 'parent-process-exec-nonpersistent.js'); -var persistentPid = -1; +let persistentPid = -1; -const execParent = execFile(process.execPath, [ childPath], { - timeout: 1000 -}); +const execParent = cp.fork(childPath); -execParent.stdout.on('data', function(data) { - persistentPid = data; -}); +execParent.on('message', common.mustCall((msg) => { + persistentPid = msg; +})); + +execParent.on('close', common.mustCall((code, sig) => { + assert.equal(sig, null); +})); process.on('exit', () => { assert.notStrictEqual(persistentPid, -1); - assert.throws(function(data) { - process.kill(execParent.pid); - }); - assert.doesNotThrow(function() { - process.kill(persistentPid); - }); }); From 01779e6b931bdad8eb55ac97ffe9ed49b80a5291 Mon Sep 17 00:00:00 2001 From: Jessica Quynh Tran Date: Thu, 24 Nov 2016 17:20:37 -0500 Subject: [PATCH 5/5] sync branch to test on Windows --- test/fixtures/parent-process-exec-nonpersistent.js | 1 - test/parallel/test-child-process-exec-detached.js | 13 +++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test/fixtures/parent-process-exec-nonpersistent.js b/test/fixtures/parent-process-exec-nonpersistent.js index e62dd9ae4621..68ee6e3e35da 100644 --- a/test/fixtures/parent-process-exec-nonpersistent.js +++ b/test/fixtures/parent-process-exec-nonpersistent.js @@ -5,7 +5,6 @@ const childPath = path.join(__dirname, 'child-process-persistent.js'); var child = execFile(process.execPath, [ childPath ], { detached: true, - timeout: 100, stdio: 'ignore' }); diff --git a/test/parallel/test-child-process-exec-detached.js b/test/parallel/test-child-process-exec-detached.js index a3541adbd2f4..d57a88562ee3 100644 --- a/test/parallel/test-child-process-exec-detached.js +++ b/test/parallel/test-child-process-exec-detached.js @@ -7,16 +7,17 @@ const childPath = path.join(common.fixturesDir, 'parent-process-exec-nonpersiste let persistentPid = -1; -const execParent = cp.fork(childPath); +const child = cp.fork(childPath); -execParent.on('message', common.mustCall((msg) => { +child.on('message', common.mustCall((msg) => { persistentPid = msg; })); -execParent.on('close', common.mustCall((code, sig) => { - assert.equal(sig, null); -})); - process.on('exit', () => { assert.notStrictEqual(persistentPid, -1); }); + +setTimeout(function() { + // *nix: test that the child process it has the gid === pid + process.kill(persistentPid); +}, 150); \ No newline at end of file