|
1 | 1 | // Qa Lab plugin module implements gateway child behavior. |
2 | | -import { spawn, type ChildProcess } from "node:child_process"; |
| 2 | +import { spawn, spawnSync, type ChildProcess } from "node:child_process"; |
3 | 3 | import { randomUUID } from "node:crypto"; |
4 | 4 | import { createWriteStream, existsSync, type WriteStream } from "node:fs"; |
5 | 5 | import fs from "node:fs/promises"; |
@@ -361,6 +361,7 @@ export const testing = {
|
361 | 361 | resolveQaRuntimeHostVersion, |
362 | 362 | createQaGatewayChildLogCollector, |
363 | 363 | createQaBundledPluginsDir, |
| 364 | + signalQaGatewayChildProcessTree, |
364 | 365 | stopQaGatewayChildProcessTree, |
365 | 366 | }; |
366 | 367 | |
@@ -390,12 +391,47 @@ function isQaGatewayChildProcessTreeAlive(child: ChildProcess) {
|
390 | 391 | } |
391 | 392 | } |
392 | 393 | |
393 | | -function signalQaGatewayChildProcessTree(child: ChildProcess, signal: NodeJS.Signals) { |
| 394 | +type QaGatewayTaskkillRunner = typeof spawnSync; |
| 395 | + |
| 396 | +function signalQaGatewayWindowsProcessTree( |
| 397 | +pid: number, |
| 398 | +signal: NodeJS.Signals, |
| 399 | +runTaskkill: QaGatewayTaskkillRunner = spawnSync, |
| 400 | +) { |
| 401 | +const args = ["/PID", String(pid), "/T"]; |
| 402 | +if (signal === "SIGKILL") { |
| 403 | +args.push("/F"); |
| 404 | +} |
| 405 | +const result = runTaskkill("taskkill", args, { |
| 406 | +stdio: "ignore", |
| 407 | +windowsHide: true, |
| 408 | +}); |
| 409 | +if (!result.error && result.status === 0) { |
| 410 | +return true; |
| 411 | +} |
| 412 | +if (signal !== "SIGKILL") { |
| 413 | +const forceResult = runTaskkill("taskkill", [...args, "/F"], { |
| 414 | +stdio: "ignore", |
| 415 | +windowsHide: true, |
| 416 | +}); |
| 417 | +return !forceResult.error && forceResult.status === 0; |
| 418 | +} |
| 419 | +return false; |
| 420 | +} |
| 421 | + |
| 422 | +function signalQaGatewayChildProcessTree( |
| 423 | +child: ChildProcess, |
| 424 | +signal: NodeJS.Signals, |
| 425 | +runTaskkill: QaGatewayTaskkillRunner = spawnSync, |
| 426 | +) { |
394 | 427 | if (!child.pid) { |
395 | 428 | return; |
396 | 429 | } |
397 | 430 | try { |
398 | 431 | if (process.platform === "win32") { |
| 432 | +if (signalQaGatewayWindowsProcessTree(child.pid, signal, runTaskkill)) { |
| 433 | +return; |
| 434 | +} |
399 | 435 | child.kill(signal); |
400 | 436 | return; |
401 | 437 | } |
|