diff --git a/lib/child_process.js b/lib/child_process.js index 1b645e43c8151b..28290f65a0fb2d 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -365,14 +365,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 6012072eb297d1..ca430d17cfe1bb 100644 --- a/test/parallel/test-child-process-execfile.js +++ b/test/parallel/test-child-process-execfile.js @@ -4,6 +4,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'); @@ -69,5 +70,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); }