Skip to content

Commit 0336882

Browse files
ehmickysindresorhus
authored andcommitted
Merge forceKill and forceKillAfter options (#285)
1 parent 7e2c835 commit 0336882

File tree

5 files changed

+31
-38
lines changed

5 files changed

+31
-38
lines changed

index.d.ts

+3-8
Original file line numberDiff line numberDiff line change
@@ -280,19 +280,14 @@ declare namespace execa {
280280
}
281281

282282
interface KillOptions {
283-
/**
284-
If the first signal does not terminate the child process after a specified timeout, a `SIGKILL` signal will be sent to the process.
285-
286-
@default true
287-
*/
288-
forceKill?: boolean;
289-
290283
/**
291284
Milliseconds to wait for the child process to terminate before sending `SIGKILL`.
292285
286+
Can be disabled with `false`.
287+
293288
@default 5000
294289
*/
295-
forceKillAfter?: number;
290+
forceKillAfterTimeout?: number | false;
296291
}
297292

298293
interface ExecaChildPromise<StdoutErrorType> {

index.js

+10-6
Original file line numberDiff line numberDiff line change
@@ -231,21 +231,25 @@ function setKillTimeout(kill, signal, options, killResult) {
231231
}, timeout).unref();
232232
}
233233

234-
function shouldForceKill(signal, {forceKill}, killResult) {
235-
return isSigterm(signal) && forceKill !== false && killResult;
234+
function shouldForceKill(signal, {forceKillAfterTimeout}, killResult) {
235+
return isSigterm(signal) && forceKillAfterTimeout !== false && killResult;
236236
}
237237

238238
function isSigterm(signal) {
239239
return signal === os.constants.signals.SIGTERM ||
240240
(typeof signal === 'string' && signal.toUpperCase() === 'SIGTERM');
241241
}
242242

243-
function getForceKillAfterTimeout({forceKillAfter = DEFAULT_FORCE_KILL_TIMEOUT}) {
244-
if (!Number.isInteger(forceKillAfter) || forceKillAfter < 0) {
245-
throw new TypeError(`Expected the \`forceKillAfter\` option to be a non-negative integer, got \`${forceKillAfter}\` (${typeof forceKillAfter})`);
243+
function getForceKillAfterTimeout({forceKillAfterTimeout = true}) {
244+
if (forceKillAfterTimeout === true) {
245+
return DEFAULT_FORCE_KILL_TIMEOUT;
246246
}
247247

248-
return forceKillAfter;
248+
if (!Number.isInteger(forceKillAfterTimeout) || forceKillAfterTimeout < 0) {
249+
throw new TypeError(`Expected the \`forceKillAfterTimeout\` option to be a non-negative integer, got \`${forceKillAfterTimeout}\` (${typeof forceKillAfterTimeout})`);
250+
}
251+
252+
return forceKillAfterTimeout;
249253
}
250254

251255
const execa = (file, args, options) => {

index.test-d.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,9 @@ execa('unicorns').kill();
123123
execa('unicorns').kill('SIGKILL');
124124
execa('unicorns').kill(undefined);
125125
execa('unicorns').kill('SIGKILL', {});
126-
execa('unicorns').kill('SIGKILL', {forceKill: true});
127-
execa('unicorns').kill('SIGKILL', {forceKill: false});
128-
execa('unicorns').kill('SIGKILL', {forceKillAfter: 42});
129-
execa('unicorns').kill('SIGKILL', {forceKillAfter: undefined});
126+
execa('unicorns').kill('SIGKILL', {forceKillAfterTimeout: false});
127+
execa('unicorns').kill('SIGKILL', {forceKillAfterTimeout: 42});
128+
execa('unicorns').kill('SIGKILL', {forceKillAfterTimeout: undefined});
130129

131130
expectType<ExecaChildProcess<string>>(execa('unicorns'));
132131
expectType<ExecaReturnValue<string>>(await execa('unicorns'));

readme.md

+5-10
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ try {
117117
const subprocess = execa('node');
118118
setTimeout(() => {
119119
subprocess.kill('SIGTERM', {
120-
forceKillAfter: 2000
120+
forceKillAfterTimeout: 2000
121121
});
122122
}, 1000);
123123
```
@@ -140,20 +140,15 @@ Returns a [`child_process` instance](https://nodejs.org/api/child_process.html#c
140140

141141
Same as the original [`child_process#kill()`](https://nodejs.org/api/child_process.html#child_process_subprocess_kill_signal) except: if `signal` is `SIGTERM` (the default value) and the child process is not terminated after 5 seconds, force it by sending `SIGKILL`.
142142

143-
##### options.forceKill
143+
##### options.forceKillAfterTimeout
144144

145-
Type: `boolean`<br>
146-
Default: `true`
147-
148-
If the first signal does not terminate the child process after a specified timeout, a `SIGKILL` signal will be sent to the process.
149-
150-
##### options.forceKillAfter
151-
152-
Type: `string`<br>
145+
Type: `number | false`<br>
153146
Default: `5000`
154147

155148
Milliseconds to wait for the child process to terminate before sending `SIGKILL`.
156149

150+
Can be disabled with `false`.
151+
157152
#### cancel()
158153

159154
Similar to [`childProcess.kill()`](https://nodejs.org/api/child_process.html#child_process_subprocess_kill_signal). This is preferred when cancelling the child process execution as the error is more descriptive and [`childProcessResult.isCanceled`](#iscanceled) is set to `true`.

test.js

+10-10
Original file line numberDiff line numberDiff line change
@@ -129,31 +129,31 @@ test('kill("SIGKILL") should terminate cleanly', async t => {
129129
// `SIGTERM` cannot be caught on Windows, and it always aborts the process (like `SIGKILL` on Unix).
130130
// Therefore, this feature and those tests do not make sense on Windows.
131131
if (process.platform !== 'win32') {
132-
test('`forceKill: false` should not kill after a timeout', async t => {
132+
test('`forceKillAfterTimeout: false` should not kill after a timeout', async t => {
133133
const subprocess = execa('node', ['fixtures/no-killable'], {stdio: ['ipc']});
134134
await pEvent(subprocess, 'message');
135135

136-
subprocess.kill('SIGTERM', {forceKill: false, forceKillAfter: 50});
136+
subprocess.kill('SIGTERM', {forceKillAfterTimeout: false});
137137

138138
t.true(isRunning(subprocess.pid));
139139
subprocess.kill('SIGKILL');
140140
});
141141

142-
test('`forceKillAfter: number` should kill after a timeout', async t => {
142+
test('`forceKillAfterTimeout: number` should kill after a timeout', async t => {
143143
const subprocess = execa('node', ['fixtures/no-killable'], {stdio: ['ipc']});
144144
await pEvent(subprocess, 'message');
145145

146-
subprocess.kill('SIGTERM', {forceKillAfter: 50});
146+
subprocess.kill('SIGTERM', {forceKillAfterTimeout: 50});
147147

148148
const {signal} = await t.throwsAsync(subprocess);
149149
t.is(signal, 'SIGKILL');
150150
});
151151

152-
test('`forceKill: true` should kill after a timeout', async t => {
152+
test('`forceKillAfterTimeout: true` should kill after a timeout', async t => {
153153
const subprocess = execa('node', ['fixtures/no-killable'], {stdio: ['ipc']});
154154
await pEvent(subprocess, 'message');
155155

156-
subprocess.kill('SIGTERM', {forceKill: true});
156+
subprocess.kill('SIGTERM', {forceKillAfterTimeout: true});
157157

158158
const {signal} = await t.throwsAsync(subprocess);
159159
t.is(signal, 'SIGKILL');
@@ -169,15 +169,15 @@ if (process.platform !== 'win32') {
169169
t.is(signal, 'SIGKILL');
170170
});
171171

172-
test('`forceKillAfter` should not be a float', t => {
172+
test('`forceKillAfterTimeout` should not be a float', t => {
173173
t.throws(() => {
174-
execa('noop').kill('SIGTERM', {forceKillAfter: 0.5});
174+
execa('noop').kill('SIGTERM', {forceKillAfterTimeout: 0.5});
175175
}, {instanceOf: TypeError, message: /non-negative integer/});
176176
});
177177

178-
test('`forceKillAfter` should not be negative', t => {
178+
test('`forceKillAfterTimeout` should not be negative', t => {
179179
t.throws(() => {
180-
execa('noop').kill('SIGTERM', {forceKillAfter: -1});
180+
execa('noop').kill('SIGTERM', {forceKillAfterTimeout: -1});
181181
}, {instanceOf: TypeError, message: /non-negative integer/});
182182
});
183183
}

0 commit comments

Comments
 (0)