@db-lyon/flowkit 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/guard/index.d.ts +7 -0
- package/dist/guard/index.d.ts.map +1 -0
- package/dist/guard/index.js +5 -0
- package/dist/guard/index.js.map +1 -0
- package/dist/guard/pipeline.d.ts +22 -0
- package/dist/guard/pipeline.d.ts.map +1 -0
- package/dist/guard/pipeline.js +45 -0
- package/dist/guard/pipeline.js.map +1 -0
- package/dist/guard/registry.d.ts +20 -0
- package/dist/guard/registry.d.ts.map +1 -0
- package/dist/guard/registry.js +33 -0
- package/dist/guard/registry.js.map +1 -0
- package/dist/guard/task-guards.d.ts +89 -0
- package/dist/guard/task-guards.d.ts.map +1 -0
- package/dist/guard/task-guards.js +83 -0
- package/dist/guard/task-guards.js.map +1 -0
- package/dist/guard/types.d.ts +49 -0
- package/dist/guard/types.d.ts.map +1 -0
- package/dist/guard/types.js +38 -0
- package/dist/guard/types.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/references.d.ts.map +1 -1
- package/dist/references.js +6 -0
- package/dist/references.js.map +1 -1
- package/dist/task/shell-task.d.ts +2 -0
- package/dist/task/shell-task.d.ts.map +1 -1
- package/dist/task/shell-task.js +186 -40
- package/dist/task/shell-task.js.map +1 -1
- package/dist/task/shell-termination.d.ts +34 -0
- package/dist/task/shell-termination.d.ts.map +1 -0
- package/dist/task/shell-termination.js +179 -0
- package/dist/task/shell-termination.js.map +1 -0
- package/docs/api-reference.md +139 -1
- package/docs/custom-tasks.md +27 -1
- package/docs/guards.md +133 -0
- package/package.json +4 -2
package/dist/task/shell-task.js
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
2
|
import { BaseTask } from './base-task.js';
|
|
3
|
+
import { beginShellTermination, POSIX_SIGTERM_GRACE_MS, terminationGraceMs, } from './shell-termination.js';
|
|
4
|
+
/** Stable internal error text returned when a shell invocation is cancelled. */
|
|
5
|
+
const SHELL_TASK_CANCELLED_MESSAGE = 'Shell command cancelled';
|
|
6
|
+
function isAbortSignal(value) {
|
|
7
|
+
// A structural check can admit a lookalike whose addEventListener throws
|
|
8
|
+
// after spawn, recreating the detached-child leak this validation prevents.
|
|
9
|
+
return value instanceof AbortSignal;
|
|
10
|
+
}
|
|
3
11
|
/**
|
|
4
12
|
* Task that executes a shell command.
|
|
5
13
|
*
|
|
@@ -30,9 +38,21 @@ export class ShellTask extends BaseTask {
|
|
|
30
38
|
if (!this.options.command || typeof this.options.command !== 'string') {
|
|
31
39
|
throw new Error('ShellTask requires a "command" option');
|
|
32
40
|
}
|
|
41
|
+
if (this.options.signal !== undefined && !isAbortSignal(this.options.signal)) {
|
|
42
|
+
throw new Error('ShellTask "signal" must be an AbortSignal');
|
|
43
|
+
}
|
|
33
44
|
}
|
|
34
45
|
async execute() {
|
|
35
|
-
const { command, cwd, timeout = 300_000 } = this.options;
|
|
46
|
+
const { command, cwd, timeout = 300_000, signal } = this.options;
|
|
47
|
+
// Do this before creating the Promise (and, importantly, before spawn) so
|
|
48
|
+
// an already-cancelled run cannot launch a process at all.
|
|
49
|
+
if (signal?.aborted) {
|
|
50
|
+
return {
|
|
51
|
+
success: false,
|
|
52
|
+
error: new Error(SHELL_TASK_CANCELLED_MESSAGE),
|
|
53
|
+
data: { exitCode: null, signal: null, stderr: '', stdout: '' },
|
|
54
|
+
};
|
|
55
|
+
}
|
|
36
56
|
return new Promise((resolve) => {
|
|
37
57
|
// Cross-platform: route through the platform shell so command strings
|
|
38
58
|
// like "npm run build" or "echo $HOME && ls" work the same way they
|
|
@@ -41,12 +61,36 @@ export class ShellTask extends BaseTask {
|
|
|
41
61
|
cwd,
|
|
42
62
|
shell: true,
|
|
43
63
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
64
|
+
// A signal-bearing POSIX invocation gets its own process group so its
|
|
65
|
+
// shell and ordinary descendants can be terminated together. Keep the
|
|
66
|
+
// legacy spawn behavior unchanged when no signal was supplied.
|
|
67
|
+
...(signal && process.platform !== 'win32' ? { detached: true } : {}),
|
|
44
68
|
});
|
|
45
69
|
let stdoutBuf = '';
|
|
46
70
|
let stderrBuf = '';
|
|
47
71
|
let stdoutTail = '';
|
|
48
72
|
let stderrTail = '';
|
|
49
|
-
let
|
|
73
|
+
let terminalCause = 'running';
|
|
74
|
+
let settled = false;
|
|
75
|
+
let abortListenerRegistered = false;
|
|
76
|
+
let timeoutTimer;
|
|
77
|
+
let terminationTimer;
|
|
78
|
+
let escalationTimer;
|
|
79
|
+
let terminator;
|
|
80
|
+
let terminationEscalated = false;
|
|
81
|
+
let pendingTerminalClose;
|
|
82
|
+
const onStdoutData = (chunk) => {
|
|
83
|
+
stdoutBuf += chunk;
|
|
84
|
+
emitLines(chunk, 'stdout', (line) => {
|
|
85
|
+
this.logger.info({ stream: 'stdout' }, line);
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
const onStderrData = (chunk) => {
|
|
89
|
+
stderrBuf += chunk;
|
|
90
|
+
emitLines(chunk, 'stderr', (line) => {
|
|
91
|
+
this.logger.warn({ stream: 'stderr' }, line);
|
|
92
|
+
});
|
|
93
|
+
};
|
|
50
94
|
const emitLines = (chunk, tailRef, emit) => {
|
|
51
95
|
// Maintain a small tail buffer so we never emit a partial line.
|
|
52
96
|
// Each newline we see flushes everything before it as one line;
|
|
@@ -65,65 +109,167 @@ export class ShellTask extends BaseTask {
|
|
|
65
109
|
};
|
|
66
110
|
child.stdout?.setEncoding('utf-8');
|
|
67
111
|
child.stderr?.setEncoding('utf-8');
|
|
68
|
-
child.stdout?.on('data',
|
|
69
|
-
|
|
70
|
-
emitLines(chunk, 'stdout', (line) => {
|
|
71
|
-
this.logger.info({ stream: 'stdout' }, line);
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
child.stderr?.on('data', (chunk) => {
|
|
75
|
-
stderrBuf += chunk;
|
|
76
|
-
emitLines(chunk, 'stderr', (line) => {
|
|
77
|
-
this.logger.warn({ stream: 'stderr' }, line);
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
const timer = setTimeout(() => {
|
|
81
|
-
timedOut = true;
|
|
82
|
-
// SIGKILL on Windows is mapped to TerminateProcess by libuv.
|
|
83
|
-
child.kill('SIGKILL');
|
|
84
|
-
}, timeout);
|
|
112
|
+
child.stdout?.on('data', onStdoutData);
|
|
113
|
+
child.stderr?.on('data', onStderrData);
|
|
85
114
|
const flushTails = () => {
|
|
86
115
|
if (stdoutTail.length > 0) {
|
|
87
116
|
this.logger.info({ stream: 'stdout' }, stdoutTail);
|
|
88
|
-
stdoutBuf += stdoutTail;
|
|
89
117
|
stdoutTail = '';
|
|
90
118
|
}
|
|
91
119
|
if (stderrTail.length > 0) {
|
|
92
120
|
this.logger.warn({ stream: 'stderr' }, stderrTail);
|
|
93
|
-
stderrBuf += stderrTail;
|
|
94
121
|
stderrTail = '';
|
|
95
122
|
}
|
|
96
123
|
};
|
|
97
|
-
|
|
98
|
-
|
|
124
|
+
const removeAbortListener = () => {
|
|
125
|
+
if (!abortListenerRegistered)
|
|
126
|
+
return;
|
|
127
|
+
abortListenerRegistered = false;
|
|
128
|
+
signal?.removeEventListener('abort', onAbort);
|
|
129
|
+
};
|
|
130
|
+
const cleanup = () => {
|
|
131
|
+
if (timeoutTimer)
|
|
132
|
+
clearTimeout(timeoutTimer);
|
|
133
|
+
if (terminationTimer)
|
|
134
|
+
clearTimeout(terminationTimer);
|
|
135
|
+
if (escalationTimer)
|
|
136
|
+
clearTimeout(escalationTimer);
|
|
137
|
+
removeAbortListener();
|
|
138
|
+
// A bounded fallback may settle before a misbehaving child closes.
|
|
139
|
+
// Stop capturing output then, while retaining the child error handler
|
|
140
|
+
// until Node finishes closing it.
|
|
141
|
+
child.stdout?.removeListener('data', onStdoutData);
|
|
142
|
+
child.stderr?.removeListener('data', onStderrData);
|
|
143
|
+
terminator?.dispose();
|
|
144
|
+
};
|
|
145
|
+
const resultData = (exitCode, exitSignal, includeSignal = true) => {
|
|
99
146
|
flushTails();
|
|
100
|
-
|
|
147
|
+
return {
|
|
148
|
+
exitCode,
|
|
149
|
+
...(includeSignal ? { signal: exitSignal } : {}),
|
|
150
|
+
stderr: stderrBuf.trimEnd(),
|
|
151
|
+
stdout: stdoutBuf.trimEnd(),
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
const settle = (result) => {
|
|
155
|
+
if (settled)
|
|
156
|
+
return;
|
|
157
|
+
settled = true;
|
|
158
|
+
cleanup();
|
|
159
|
+
resolve(result);
|
|
160
|
+
};
|
|
161
|
+
const settleTerminal = (exitCode, exitSignal) => {
|
|
162
|
+
const data = resultData(exitCode, exitSignal);
|
|
163
|
+
settle({
|
|
164
|
+
success: false,
|
|
165
|
+
error: new Error(terminalCause === 'cancelled'
|
|
166
|
+
? SHELL_TASK_CANCELLED_MESSAGE
|
|
167
|
+
: `Shell command timed out after ${timeout}ms`),
|
|
168
|
+
data,
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
const requestTermination = (cause) => {
|
|
172
|
+
if (settled || terminalCause !== 'running')
|
|
173
|
+
return;
|
|
174
|
+
terminalCause = cause;
|
|
175
|
+
if (timeoutTimer)
|
|
176
|
+
clearTimeout(timeoutTimer);
|
|
177
|
+
removeAbortListener();
|
|
178
|
+
// Preserve the legacy no-signal timeout path exactly: kill the shell
|
|
179
|
+
// and wait for close. The bounded cancellation contract applies only
|
|
180
|
+
// when a caller supplied an AbortSignal.
|
|
181
|
+
if (cause === 'timedOut' && !signal) {
|
|
182
|
+
try {
|
|
183
|
+
child.kill('SIGKILL');
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
// The existing error/close handlers retain responsibility for the
|
|
187
|
+
// final task result.
|
|
188
|
+
}
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
try {
|
|
192
|
+
terminator = beginShellTermination(child);
|
|
193
|
+
terminator.onTreeKillComplete(() => {
|
|
194
|
+
if (!pendingTerminalClose || settled || terminalCause === 'running')
|
|
195
|
+
return;
|
|
196
|
+
const pending = pendingTerminalClose;
|
|
197
|
+
pendingTerminalClose = undefined;
|
|
198
|
+
settleTerminal(pending.exitCode, pending.exitSignal);
|
|
199
|
+
});
|
|
200
|
+
if (terminator.platform !== 'win32') {
|
|
201
|
+
escalationTimer = setTimeout(() => {
|
|
202
|
+
terminationEscalated = true;
|
|
203
|
+
terminator?.escalate();
|
|
204
|
+
if (pendingTerminalClose) {
|
|
205
|
+
const pending = pendingTerminalClose;
|
|
206
|
+
pendingTerminalClose = undefined;
|
|
207
|
+
settleTerminal(pending.exitCode, pending.exitSignal);
|
|
208
|
+
}
|
|
209
|
+
}, POSIX_SIGTERM_GRACE_MS);
|
|
210
|
+
}
|
|
211
|
+
terminationTimer = setTimeout(() => {
|
|
212
|
+
terminator?.release();
|
|
213
|
+
settleTerminal(null, null);
|
|
214
|
+
}, terminationGraceMs(terminator.platform));
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
// `close` or the bounded fallback below will settle the terminal
|
|
218
|
+
// result; a kill race must not escape as an unhandled exception.
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
const onAbort = () => requestTermination('cancelled');
|
|
222
|
+
timeoutTimer = setTimeout(() => requestTermination('timedOut'), timeout);
|
|
223
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
224
|
+
abortListenerRegistered = Boolean(signal);
|
|
225
|
+
child.on('error', (err) => {
|
|
226
|
+
if (terminalCause !== 'running') {
|
|
227
|
+
// Preserve the legacy no-signal timeout result if the kill itself
|
|
228
|
+
// errors and no `close` follows. Without this, a timeout could leave
|
|
229
|
+
// the task pending indefinitely; the original error and data shape
|
|
230
|
+
// remain intact for compatibility.
|
|
231
|
+
if (terminalCause === 'timedOut' && !signal) {
|
|
232
|
+
settle({
|
|
233
|
+
success: false,
|
|
234
|
+
error: err instanceof Error ? err : new Error(String(err)),
|
|
235
|
+
data: resultData(null, null, false),
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
settle({
|
|
101
241
|
success: false,
|
|
102
242
|
error: err instanceof Error ? err : new Error(String(err)),
|
|
103
|
-
data:
|
|
243
|
+
data: resultData(null, null, Boolean(signal)),
|
|
104
244
|
});
|
|
105
245
|
});
|
|
106
|
-
child.on('close', (code,
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
246
|
+
child.on('close', (code, exitSignal) => {
|
|
247
|
+
if (settled)
|
|
248
|
+
return;
|
|
249
|
+
if (terminalCause !== 'running') {
|
|
250
|
+
const waitsForPosixEscalation = terminator !== undefined &&
|
|
251
|
+
terminator.platform !== 'win32' &&
|
|
252
|
+
!terminationEscalated;
|
|
253
|
+
const waitsForWindowsTree = terminator?.platform === 'win32' && !terminator.isTreeKillComplete();
|
|
254
|
+
if (waitsForPosixEscalation || waitsForWindowsTree) {
|
|
255
|
+
// A root shell may close before its descendants are finished.
|
|
256
|
+
// Keep the POSIX escalation or Windows taskkill operation owned
|
|
257
|
+
// until it finishes or reaches the bounded terminal deadline.
|
|
258
|
+
pendingTerminalClose = { exitCode: code, exitSignal };
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
settleTerminal(code, exitSignal);
|
|
117
262
|
return;
|
|
118
263
|
}
|
|
264
|
+
const data = resultData(code, exitSignal);
|
|
119
265
|
if (code === 0) {
|
|
120
|
-
|
|
266
|
+
settle({ success: true, data: { output: data.stdout } });
|
|
121
267
|
return;
|
|
122
268
|
}
|
|
123
|
-
|
|
269
|
+
settle({
|
|
124
270
|
success: false,
|
|
125
|
-
error: new Error(`Shell command failed (exit ${code}): ${(
|
|
126
|
-
data
|
|
271
|
+
error: new Error(`Shell command failed (exit ${code}): ${(data.stderr || data.stdout).trimEnd()}`),
|
|
272
|
+
data,
|
|
127
273
|
});
|
|
128
274
|
});
|
|
129
275
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell-task.js","sourceRoot":"","sources":["../../src/task/shell-task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAmB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"shell-task.js","sourceRoot":"","sources":["../../src/task/shell-task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAmB,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,kBAAkB,GAEnB,MAAM,wBAAwB,CAAC;AAUhC,gFAAgF;AAChF,MAAM,4BAA4B,GAAG,yBAAyB,CAAC;AAE/D,SAAS,aAAa,CAAC,KAAc;IACnC,yEAAyE;IACzE,4EAA4E;IAC5E,OAAO,KAAK,YAAY,WAAW,CAAC;AACtC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,OAAO,SAAU,SAAQ,QAA0B;IACvD,IAAI,QAAQ;QACV,OAAO,SAAS,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;IACzC,CAAC;IAES,QAAQ;QAChB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YACtE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7E,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QAEjE,0EAA0E;QAC1E,2DAA2D;QAC3D,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,IAAI,KAAK,CAAC,4BAA4B,CAAC;gBAC9C,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;aAC/D,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,OAAO,CAAa,CAAC,OAAO,EAAE,EAAE;YACzC,sEAAsE;YACtE,oEAAoE;YACpE,sBAAsB;YACtB,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE;gBAC3B,GAAG;gBACH,KAAK,EAAE,IAAI;gBACX,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;gBACjC,sEAAsE;gBACtE,sEAAsE;gBACtE,+DAA+D;gBAC/D,GAAG,CAAC,MAAM,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACtE,CAAC,CAAC;YAEH,IAAI,SAAS,GAAG,EAAE,CAAC;YACnB,IAAI,SAAS,GAAG,EAAE,CAAC;YACnB,IAAI,UAAU,GAAG,EAAE,CAAC;YACpB,IAAI,UAAU,GAAG,EAAE,CAAC;YACpB,IAAI,aAAa,GAAyC,SAAS,CAAC;YACpE,IAAI,OAAO,GAAG,KAAK,CAAC;YACpB,IAAI,uBAAuB,GAAG,KAAK,CAAC;YACpC,IAAI,YAAuD,CAAC;YAC5D,IAAI,gBAA2D,CAAC;YAChE,IAAI,eAA0D,CAAC;YAC/D,IAAI,UAA8C,CAAC;YACnD,IAAI,oBAAoB,GAAG,KAAK,CAAC;YACjC,IAAI,oBAES,CAAC;YACd,MAAM,YAAY,GAAG,CAAC,KAAa,EAAE,EAAE;gBACrC,SAAS,IAAI,KAAK,CAAC;gBACnB,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE;oBAClC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,IAAI,CAAC,CAAC;gBAC/C,CAAC,CAAC,CAAC;YACL,CAAC,CAAC;YACF,MAAM,YAAY,GAAG,CAAC,KAAa,EAAE,EAAE;gBACrC,SAAS,IAAI,KAAK,CAAC;gBACnB,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE;oBAClC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,IAAI,CAAC,CAAC;gBAC/C,CAAC,CAAC,CAAC;YACL,CAAC,CAAC;YAEF,MAAM,SAAS,GAAG,CAChB,KAAa,EACb,OAA4B,EAC5B,IAA4B,EAC5B,EAAE;gBACF,gEAAgE;gBAChE,gEAAgE;gBAChE,gDAAgD;gBAChD,MAAM,QAAQ,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,KAAK,CAAC;gBAC1E,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACtC,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;gBACpC,IAAI,OAAO,KAAK,QAAQ;oBAAE,UAAU,GAAG,SAAS,CAAC;;oBAC5C,UAAU,GAAG,SAAS,CAAC;gBAC5B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;wBAAE,IAAI,CAAC,IAAI,CAAC,CAAC;gBAClC,CAAC;YACH,CAAC,CAAC;YAEF,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;YACnC,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;YAEnC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YACvC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YAEvC,MAAM,UAAU,GAAG,GAAG,EAAE;gBACtB,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC1B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,UAAU,CAAC,CAAC;oBACnD,UAAU,GAAG,EAAE,CAAC;gBAClB,CAAC;gBACD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC1B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,UAAU,CAAC,CAAC;oBACnD,UAAU,GAAG,EAAE,CAAC;gBAClB,CAAC;YACH,CAAC,CAAC;YAEF,MAAM,mBAAmB,GAAG,GAAG,EAAE;gBAC/B,IAAI,CAAC,uBAAuB;oBAAE,OAAO;gBACrC,uBAAuB,GAAG,KAAK,CAAC;gBAChC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAChD,CAAC,CAAC;YAEF,MAAM,OAAO,GAAG,GAAG,EAAE;gBACnB,IAAI,YAAY;oBAAE,YAAY,CAAC,YAAY,CAAC,CAAC;gBAC7C,IAAI,gBAAgB;oBAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC;gBACrD,IAAI,eAAe;oBAAE,YAAY,CAAC,eAAe,CAAC,CAAC;gBACnD,mBAAmB,EAAE,CAAC;gBACtB,mEAAmE;gBACnE,sEAAsE;gBACtE,kCAAkC;gBAClC,KAAK,CAAC,MAAM,EAAE,cAAc,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;gBACnD,KAAK,CAAC,MAAM,EAAE,cAAc,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;gBACnD,UAAU,EAAE,OAAO,EAAE,CAAC;YACxB,CAAC,CAAC;YAEF,MAAM,UAAU,GAAG,CACjB,QAAuB,EACvB,UAAiC,EACjC,aAAa,GAAG,IAAI,EACpB,EAAE;gBACF,UAAU,EAAE,CAAC;gBACb,OAAO;oBACL,QAAQ;oBACR,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAChD,MAAM,EAAE,SAAS,CAAC,OAAO,EAAE;oBAC3B,MAAM,EAAE,SAAS,CAAC,OAAO,EAAE;iBAC5B,CAAC;YACJ,CAAC,CAAC;YAEF,MAAM,MAAM,GAAG,CAAC,MAAkB,EAAE,EAAE;gBACpC,IAAI,OAAO;oBAAE,OAAO;gBACpB,OAAO,GAAG,IAAI,CAAC;gBACf,OAAO,EAAE,CAAC;gBACV,OAAO,CAAC,MAAM,CAAC,CAAC;YAClB,CAAC,CAAC;YAEF,MAAM,cAAc,GAAG,CAAC,QAAuB,EAAE,UAAiC,EAAE,EAAE;gBACpF,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;gBAC9C,MAAM,CAAC;oBACL,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,IAAI,KAAK,CACd,aAAa,KAAK,WAAW;wBAC3B,CAAC,CAAC,4BAA4B;wBAC9B,CAAC,CAAC,iCAAiC,OAAO,IAAI,CACjD;oBACD,IAAI;iBACL,CAAC,CAAC;YACL,CAAC,CAAC;YAEF,MAAM,kBAAkB,GAAG,CAAC,KAA+B,EAAE,EAAE;gBAC7D,IAAI,OAAO,IAAI,aAAa,KAAK,SAAS;oBAAE,OAAO;gBACnD,aAAa,GAAG,KAAK,CAAC;gBACtB,IAAI,YAAY;oBAAE,YAAY,CAAC,YAAY,CAAC,CAAC;gBAC7C,mBAAmB,EAAE,CAAC;gBAEtB,qEAAqE;gBACrE,qEAAqE;gBACrE,yCAAyC;gBACzC,IAAI,KAAK,KAAK,UAAU,IAAI,CAAC,MAAM,EAAE,CAAC;oBACpC,IAAI,CAAC;wBACH,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;oBACxB,CAAC;oBAAC,MAAM,CAAC;wBACP,kEAAkE;wBAClE,qBAAqB;oBACvB,CAAC;oBACD,OAAO;gBACT,CAAC;gBACD,IAAI,CAAC;oBACH,UAAU,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;oBAC1C,UAAU,CAAC,kBAAkB,CAAC,GAAG,EAAE;wBACjC,IAAI,CAAC,oBAAoB,IAAI,OAAO,IAAI,aAAa,KAAK,SAAS;4BAAE,OAAO;wBAC5E,MAAM,OAAO,GAAG,oBAAoB,CAAC;wBACrC,oBAAoB,GAAG,SAAS,CAAC;wBACjC,cAAc,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;oBACvD,CAAC,CAAC,CAAC;oBACH,IAAI,UAAU,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;wBACpC,eAAe,GAAG,UAAU,CAAC,GAAG,EAAE;4BAChC,oBAAoB,GAAG,IAAI,CAAC;4BAC5B,UAAU,EAAE,QAAQ,EAAE,CAAC;4BACvB,IAAI,oBAAoB,EAAE,CAAC;gCACzB,MAAM,OAAO,GAAG,oBAAoB,CAAC;gCACrC,oBAAoB,GAAG,SAAS,CAAC;gCACjC,cAAc,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;4BACvD,CAAC;wBACH,CAAC,EAAE,sBAAsB,CAAC,CAAC;oBAC7B,CAAC;oBACD,gBAAgB,GAAG,UAAU,CAAC,GAAG,EAAE;wBACjC,UAAU,EAAE,OAAO,EAAE,CAAC;wBACtB,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;oBAC7B,CAAC,EAAE,kBAAkB,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAC9C,CAAC;gBAAC,MAAM,CAAC;oBACP,iEAAiE;oBACjE,iEAAiE;gBACnE,CAAC;YACH,CAAC,CAAC;YAEF,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC;YAEtD,YAAY,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,CAAC;YAEzE,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3D,uBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;YAE1C,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBACxB,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;oBAChC,kEAAkE;oBAClE,qEAAqE;oBACrE,mEAAmE;oBACnE,mCAAmC;oBACnC,IAAI,aAAa,KAAK,UAAU,IAAI,CAAC,MAAM,EAAE,CAAC;wBAC5C,MAAM,CAAC;4BACL,OAAO,EAAE,KAAK;4BACd,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;4BAC1D,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC;yBACpC,CAAC,CAAC;oBACL,CAAC;oBACD,OAAO;gBACT,CAAC;gBACD,MAAM,CAAC;oBACL,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;oBAC1D,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;iBAC9C,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE;gBACrC,IAAI,OAAO;oBAAE,OAAO;gBACpB,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;oBAChC,MAAM,uBAAuB,GAC3B,UAAU,KAAK,SAAS;wBACxB,UAAU,CAAC,QAAQ,KAAK,OAAO;wBAC/B,CAAC,oBAAoB,CAAC;oBACxB,MAAM,mBAAmB,GACvB,UAAU,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC;oBACvE,IAAI,uBAAuB,IAAI,mBAAmB,EAAE,CAAC;wBACnD,8DAA8D;wBAC9D,gEAAgE;wBAChE,8DAA8D;wBAC9D,oBAAoB,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;wBACtD,OAAO;oBACT,CAAC;oBACD,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;oBACjC,OAAO;gBACT,CAAC;gBACD,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;gBAC1C,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;oBACf,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;oBACzD,OAAO;gBACT,CAAC;gBACD,MAAM,CAAC;oBACL,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,IAAI,KAAK,CACd,8BAA8B,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CACjF;oBACD,IAAI;iBACL,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type ChildProcess, type SpawnOptions } from 'node:child_process';
|
|
2
|
+
export declare const POSIX_SIGTERM_GRACE_MS = 250;
|
|
3
|
+
export declare const POSIX_TERMINATION_GRACE_MS = 1000;
|
|
4
|
+
export declare const WINDOWS_TERMINATION_GRACE_MS = 3000;
|
|
5
|
+
type SpawnProcess = (command: string, args: readonly string[], options: SpawnOptions) => ChildProcess;
|
|
6
|
+
export interface ShellTerminationDependencies {
|
|
7
|
+
platform?: NodeJS.Platform;
|
|
8
|
+
spawnProcess?: SpawnProcess;
|
|
9
|
+
killProcessGroup?: (pid: number, signal: NodeJS.Signals) => void;
|
|
10
|
+
}
|
|
11
|
+
export interface ShellTerminationHandle {
|
|
12
|
+
readonly platform: NodeJS.Platform;
|
|
13
|
+
/** Whether the Windows tree helper has finished or failed. */
|
|
14
|
+
isTreeKillComplete(): boolean;
|
|
15
|
+
/** Notify ShellTask when it is safe to combine tree and root completion. */
|
|
16
|
+
onTreeKillComplete(listener: () => void): void;
|
|
17
|
+
/** Escalate a cooperative POSIX stop, or force the Windows root/helper. */
|
|
18
|
+
escalate(): void;
|
|
19
|
+
/** Release handles after the bounded terminal deadline. */
|
|
20
|
+
release(): void;
|
|
21
|
+
/** Stop helper ownership after the shell has closed normally. */
|
|
22
|
+
dispose(): void;
|
|
23
|
+
}
|
|
24
|
+
export declare function terminationGraceMs(platform: NodeJS.Platform): number;
|
|
25
|
+
/**
|
|
26
|
+
* Start termination for one shell invocation.
|
|
27
|
+
*
|
|
28
|
+
* This module is deliberately internal. Passing the platform and process
|
|
29
|
+
* functions as dependencies makes the policy testable on every CI platform
|
|
30
|
+
* without changing ShellTask's public API or relying on global mutable state.
|
|
31
|
+
*/
|
|
32
|
+
export declare function beginShellTermination(child: ChildProcess, dependencies?: ShellTerminationDependencies): ShellTerminationHandle;
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=shell-termination.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell-termination.d.ts","sourceRoot":"","sources":["../../src/task/shell-termination.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEjF,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAC1C,eAAO,MAAM,0BAA0B,OAAQ,CAAC;AAChD,eAAO,MAAM,4BAA4B,OAAQ,CAAC;AAElD,KAAK,YAAY,GAAG,CAClB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,EAAE,YAAY,KAClB,YAAY,CAAC;AAElB,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI,CAAC;CAClE;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;IACnC,8DAA8D;IAC9D,kBAAkB,IAAI,OAAO,CAAC;IAC9B,4EAA4E;IAC5E,kBAAkB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAC/C,2EAA2E;IAC3E,QAAQ,IAAI,IAAI,CAAC;IACjB,2DAA2D;IAC3D,OAAO,IAAI,IAAI,CAAC;IAChB,iEAAiE;IACjE,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,GAAG,MAAM,CAEpE;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,YAAY,EACnB,YAAY,GAAE,4BAAiC,GAC9C,sBAAsB,CAyJxB"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
export const POSIX_SIGTERM_GRACE_MS = 250;
|
|
3
|
+
export const POSIX_TERMINATION_GRACE_MS = 1_000;
|
|
4
|
+
export const WINDOWS_TERMINATION_GRACE_MS = 3_000;
|
|
5
|
+
export function terminationGraceMs(platform) {
|
|
6
|
+
return platform === 'win32' ? WINDOWS_TERMINATION_GRACE_MS : POSIX_TERMINATION_GRACE_MS;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Start termination for one shell invocation.
|
|
10
|
+
*
|
|
11
|
+
* This module is deliberately internal. Passing the platform and process
|
|
12
|
+
* functions as dependencies makes the policy testable on every CI platform
|
|
13
|
+
* without changing ShellTask's public API or relying on global mutable state.
|
|
14
|
+
*/
|
|
15
|
+
export function beginShellTermination(child, dependencies = {}) {
|
|
16
|
+
const platform = dependencies.platform ?? process.platform;
|
|
17
|
+
const spawnProcess = dependencies.spawnProcess ?? spawn;
|
|
18
|
+
const killProcessGroup = dependencies.killProcessGroup ??
|
|
19
|
+
((pid, signal) => {
|
|
20
|
+
process.kill(pid, signal);
|
|
21
|
+
});
|
|
22
|
+
let active = true;
|
|
23
|
+
let escalated = false;
|
|
24
|
+
let rootForceRequested = false;
|
|
25
|
+
let treeKiller;
|
|
26
|
+
let treeKillerFinished = false;
|
|
27
|
+
let treeKillComplete = platform !== 'win32' || child.pid === undefined;
|
|
28
|
+
const treeKillListeners = new Set();
|
|
29
|
+
const markTreeKillComplete = () => {
|
|
30
|
+
if (treeKillComplete)
|
|
31
|
+
return;
|
|
32
|
+
treeKillComplete = true;
|
|
33
|
+
for (const listener of treeKillListeners)
|
|
34
|
+
listener();
|
|
35
|
+
treeKillListeners.clear();
|
|
36
|
+
};
|
|
37
|
+
const killRoot = (signal) => {
|
|
38
|
+
if (!active)
|
|
39
|
+
return;
|
|
40
|
+
if (signal === 'SIGKILL' && rootForceRequested)
|
|
41
|
+
return;
|
|
42
|
+
try {
|
|
43
|
+
const sent = child.kill(signal);
|
|
44
|
+
if (signal === 'SIGKILL' && sent)
|
|
45
|
+
rootForceRequested = true;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// The shell may have closed between the terminal event and this call.
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
const killGroup = (signal) => {
|
|
52
|
+
if (!active || child.pid === undefined) {
|
|
53
|
+
killRoot(signal);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
killProcessGroup(-child.pid, signal);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// A missing process group or unsupported group signal falls back to the
|
|
61
|
+
// direct shell. This cannot promise termination of escaped descendants.
|
|
62
|
+
killRoot(signal);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const stopTreeKiller = () => {
|
|
66
|
+
if (!treeKiller || treeKillerFinished)
|
|
67
|
+
return;
|
|
68
|
+
// Retain an error handler because a forced helper close may race an error.
|
|
69
|
+
treeKiller.once('error', () => undefined);
|
|
70
|
+
try {
|
|
71
|
+
treeKiller.kill('SIGKILL');
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// The helper may already be exiting.
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
treeKiller.unref();
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// Releasing the task result must not be defeated by an unref race.
|
|
81
|
+
}
|
|
82
|
+
treeKillerFinished = true;
|
|
83
|
+
};
|
|
84
|
+
if (platform === 'win32' && child.pid !== undefined) {
|
|
85
|
+
try {
|
|
86
|
+
treeKiller = spawnProcess('taskkill', ['/pid', String(child.pid), '/T', '/F'], { stdio: 'ignore', windowsHide: true });
|
|
87
|
+
const killOnError = () => {
|
|
88
|
+
if (!active)
|
|
89
|
+
return;
|
|
90
|
+
killRoot('SIGKILL');
|
|
91
|
+
markTreeKillComplete();
|
|
92
|
+
};
|
|
93
|
+
treeKiller.once('error', killOnError);
|
|
94
|
+
treeKiller.once('close', (code) => {
|
|
95
|
+
if (!active)
|
|
96
|
+
return;
|
|
97
|
+
treeKillerFinished = true;
|
|
98
|
+
if (code !== 0)
|
|
99
|
+
killRoot('SIGKILL');
|
|
100
|
+
markTreeKillComplete();
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
killRoot('SIGKILL');
|
|
105
|
+
markTreeKillComplete();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
// Cooperative first phase. ShellTask schedules the bounded SIGKILL
|
|
110
|
+
// escalation so normal commands can flush and clean up.
|
|
111
|
+
killGroup('SIGTERM');
|
|
112
|
+
}
|
|
113
|
+
const escalate = () => {
|
|
114
|
+
if (!active || escalated)
|
|
115
|
+
return;
|
|
116
|
+
escalated = true;
|
|
117
|
+
if (platform === 'win32') {
|
|
118
|
+
killRoot('SIGKILL');
|
|
119
|
+
stopTreeKiller();
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
killGroup('SIGKILL');
|
|
123
|
+
};
|
|
124
|
+
const dispose = () => {
|
|
125
|
+
if (!active)
|
|
126
|
+
return;
|
|
127
|
+
treeKillListeners.clear();
|
|
128
|
+
try {
|
|
129
|
+
stopTreeKiller();
|
|
130
|
+
}
|
|
131
|
+
finally {
|
|
132
|
+
active = false;
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
const release = () => {
|
|
136
|
+
if (!active)
|
|
137
|
+
return;
|
|
138
|
+
treeKillListeners.clear();
|
|
139
|
+
escalate();
|
|
140
|
+
try {
|
|
141
|
+
child.stdout?.destroy();
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
// The stream may have closed between escalation and release.
|
|
145
|
+
}
|
|
146
|
+
try {
|
|
147
|
+
child.stderr?.destroy();
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
// The stream may have closed between escalation and release.
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
child.unref();
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
// A bounded result still settles if Node rejects an unref race.
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
stopTreeKiller();
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
active = false;
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
return {
|
|
166
|
+
platform,
|
|
167
|
+
isTreeKillComplete: () => treeKillComplete,
|
|
168
|
+
onTreeKillComplete: (listener) => {
|
|
169
|
+
if (treeKillComplete)
|
|
170
|
+
listener();
|
|
171
|
+
else
|
|
172
|
+
treeKillListeners.add(listener);
|
|
173
|
+
},
|
|
174
|
+
escalate,
|
|
175
|
+
release,
|
|
176
|
+
dispose,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=shell-termination.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell-termination.js","sourceRoot":"","sources":["../../src/task/shell-termination.ts"],"names":[],"mappings":"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"}
|