diff options
author | Benjamin Gruenbaum <benjamingr@gmail.com> | 2020-12-07 12:54:50 +0200 |
---|---|---|
committer | Benjamin Gruenbaum <benjamingr@gmail.com> | 2020-12-22 17:53:00 +0200 |
commit | f0a0e3c6b3fd55d7a7cadf310ef4a443c56082b9 (patch) | |
tree | ca0d82ab60fa3403d18a530f1afa11dd52d31e92 | |
parent | 1623aff55c960e6e8d5c9fa534b7f49d4506a1b1 (diff) | |
download | ios-node-v8-f0a0e3c6b3fd55d7a7cadf310ef4a443c56082b9.tar.gz ios-node-v8-f0a0e3c6b3fd55d7a7cadf310ef4a443c56082b9.tar.bz2 ios-node-v8-f0a0e3c6b3fd55d7a7cadf310ef4a443c56082b9.zip |
child_process: clean event listener correctly
I was working on AbortSignal for spawn and noticed there is a leak in
the current code for AbortSignal support in child_process since it
removes the wrong listener. I used the new signal as argument feature
to make removing the listener easier and added a test.
PR-URL: https://github.com/nodejs/node/pull/36424
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Rich Trott <rtrott@gmail.com>
-rw-r--r-- | lib/child_process.js | 9 | ||||
-rw-r--r-- | test/parallel/test-child-process-execfile.js | 11 |
2 files changed, 15 insertions, 5 deletions
diff --git a/lib/child_process.js b/lib/child_process.js index ae5a5f6587..29a6450210 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -378,14 +378,13 @@ function execFile(file /* , args, options, callback */) { if (options.signal.aborted) { process.nextTick(() => kill()); } else { + const childController = new AbortController(); options.signal.addEventListener('abort', () => { - if (!ex) { + if (!ex) ex = new AbortError(); - } kill(); - }); - const remove = () => options.signal.removeEventListener('abort', kill); - child.once('close', remove); + }, { signal: childController.signal }); + child.once('close', () => childController.abort()); } } diff --git a/test/parallel/test-child-process-execfile.js b/test/parallel/test-child-process-execfile.js index a6345a7e5f..aec80b4e2b 100644 --- a/test/parallel/test-child-process-execfile.js +++ b/test/parallel/test-child-process-execfile.js @@ -3,6 +3,7 @@ const common = require('../common'); const assert = require('assert'); const execFile = require('child_process').execFile; +const { getEventListeners } = require('events'); const { getSystemErrorName } = require('util'); const fixtures = require('../common/fixtures'); @@ -68,5 +69,15 @@ const execOpts = { encoding: 'utf8', shell: true }; execFile(process.execPath, [echoFixture, 0], { signal: 'hello' }, callback); }, { code: 'ERR_INVALID_ARG_TYPE', name: 'TypeError' }); +} +{ + // Verify that the process completing removes the abort listener + const ac = new AbortController(); + const { signal } = ac; + const callback = common.mustCall((err) => { + assert.strictEqual(getEventListeners(ac.signal).length, 0); + assert.strictEqual(err, null); + }); + execFile(process.execPath, [fixture, 0], { signal }, callback); } |