send to the entire process group

This commit is contained in:
Simon Knott 2024-11-07 12:16:36 +00:00
parent 220ed29dbe
commit 5bf5fcf61d
5 changed files with 10 additions and 12 deletions

View file

@ -619,7 +619,7 @@ export default defineConfig({
- `stdout` ?<["pipe"|"ignore"]> If `"pipe"`, it will pipe the stdout of the command to the process stdout. If `"ignore"`, it will ignore the stdout of the command. Default to `"ignore"`. - `stdout` ?<["pipe"|"ignore"]> If `"pipe"`, it will pipe the stdout of the command to the process stdout. If `"ignore"`, it will ignore the stdout of the command. Default to `"ignore"`.
- `stderr` ?<["pipe"|"ignore"]> Whether to pipe the stderr of the command to the process stderr or ignore it. Defaults to `"pipe"`. - `stderr` ?<["pipe"|"ignore"]> Whether to pipe the stderr of the command to the process stderr or ignore it. Defaults to `"pipe"`.
- `timeout` ?<[int]> How long to wait for the process to start up and be available in milliseconds. Defaults to 60000. - `timeout` ?<[int]> How long to wait for the process to start up and be available in milliseconds. Defaults to 60000.
- `kill` ?<[Object]> How to shut down the process gracefully. If unspecified, the process group is forcefully `SIGKILL`ed. If set to `{ SIGINT: 500 }`, the top process is sent a `SIGINT` signal, followed by `SIGKILL` if it doesn't exit within 500ms. You can also use `SIGTERM` instead. A `0` timeout means no `SIGKILL` will be sent. Windows doesn't support `SIGINT` and `SIGTERM` signals, so this option is ignored. - `kill` ?<[Object]> How to shut down the process gracefully. If unspecified, the process group is forcefully `SIGKILL`ed. If set to `{ SIGINT: 500 }`, the process group is sent a `SIGINT` signal, followed by `SIGKILL` if it doesn't exit within 500ms. You can also use `SIGTERM` instead. A `0` timeout means no `SIGKILL` will be sent. Windows doesn't support `SIGINT` and `SIGTERM` signals, so this option is ignored.
- `SIGINT` ?<[int]> - `SIGINT` ?<[int]>
- `SIGTERM` ?<[int]> - `SIGTERM` ?<[int]>
- `url` ?<[string]> The url on your http server that is expected to return a 2xx, 3xx, 400, 401, 402, or 403 status code when the server is ready to accept connections. Redirects (3xx status codes) are being followed and the new location is checked. Either `port` or `url` should be specified. - `url` ?<[string]> The url on your http server that is expected to return a 2xx, 3xx, 400, 401, 402, or 403 status code when the server is ready to accept connections. Redirects (3xx status codes) are being followed and the new location is checked. Either `port` or `url` should be specified.

View file

@ -37,7 +37,7 @@ export default defineConfig({
| `stdout` | If `"pipe"`, it will pipe the stdout of the command to the process stdout. If `"ignore"`, it will ignore the stdout of the command. Default to `"ignore"`. | | `stdout` | If `"pipe"`, it will pipe the stdout of the command to the process stdout. If `"ignore"`, it will ignore the stdout of the command. Default to `"ignore"`. |
| `stderr` | Whether to pipe the stderr of the command to the process stderr or ignore it. Defaults to `"pipe"`. | | `stderr` | Whether to pipe the stderr of the command to the process stderr or ignore it. Defaults to `"pipe"`. |
| `timeout` | How long to wait for the process to start up and be available in milliseconds. Defaults to 60000. | | `timeout` | How long to wait for the process to start up and be available in milliseconds. Defaults to 60000. |
| `kill` | How to shut down the process gracefully. If unspecified, the process group is forcefully `SIGKILL`ed. If set to `{ SIGINT: 500 }`, the top process is sent a `SIGINT` signal, followed by `SIGKILL` if it doesn't exit within 500ms. You can also use `SIGTERM` instead. A `0` timeout means no `SIGKILL` will be sent. Windows doesn't support `SIGINT` and `SIGTERM` signals, so this option is ignored. | | `kill` | How to shut down the process gracefully. If unspecified, the process group is forcefully `SIGKILL`ed. If set to `{ SIGINT: 500 }`, the process group is sent a `SIGINT` signal, followed by `SIGKILL` if it doesn't exit within 500ms. You can also use `SIGTERM` instead. A `0` timeout means no `SIGKILL` will be sent. Windows doesn't support `SIGINT` and `SIGTERM` signals, so this option is ignored. |
## Adding a server timeout ## Adding a server timeout

View file

@ -180,7 +180,7 @@ export async function launchProcess(options: LaunchProcessOptions): Promise<Laun
let processClosed = false; let processClosed = false;
let fulfillCleanup = () => {}; let fulfillCleanup = () => {};
const waitForCleanup = new Promise<void>(f => fulfillCleanup = f); const waitForCleanup = new Promise<void>(f => fulfillCleanup = f);
spawnedProcess.once('exit', (exitCode, signal) => { spawnedProcess.once('close', (exitCode, signal) => {
options.log(`[pid=${spawnedProcess.pid}] <process did exit: exitCode=${exitCode}, signal=${signal}>`); options.log(`[pid=${spawnedProcess.pid}] <process did exit: exitCode=${exitCode}, signal=${signal}>`);
processClosed = true; processClosed = true;
gracefullyCloseSet.delete(gracefullyClose); gracefullyCloseSet.delete(gracefullyClose);
@ -215,18 +215,18 @@ export async function launchProcess(options: LaunchProcessOptions): Promise<Laun
} }
gracefullyClosing = true; gracefullyClosing = true;
options.log(`[pid=${spawnedProcess.pid}] <gracefully close start>`); options.log(`[pid=${spawnedProcess.pid}] <gracefully close start>`);
await options.attemptToGracefullyClose().catch(() => killProcess(true)); await options.attemptToGracefullyClose().catch((e) => killProcess());
await waitForCleanup; // Ensure the process is dead and we have cleaned up. await waitForCleanup; // Ensure the process is dead and we have cleaned up.
options.log(`[pid=${spawnedProcess.pid}] <gracefully close end>`); options.log(`[pid=${spawnedProcess.pid}] <gracefully close end>`);
} }
// This method has to be sync to be used in the 'exit' event handler. // This method has to be sync to be used in the 'exit' event handler.
function killProcess(evenIfAlreadyKilled = false) { function killProcess() {
gracefullyCloseSet.delete(gracefullyClose); gracefullyCloseSet.delete(gracefullyClose);
killSet.delete(killProcessAndCleanup); killSet.delete(killProcessAndCleanup);
removeProcessHandlersIfNeeded(); removeProcessHandlersIfNeeded();
options.log(`[pid=${spawnedProcess.pid}] <kill>`); options.log(`[pid=${spawnedProcess.pid}] <kill>`);
if (spawnedProcess.pid && (evenIfAlreadyKilled || !spawnedProcess.killed) && !processClosed) { if (spawnedProcess.pid && !processClosed) {
options.log(`[pid=${spawnedProcess.pid}] <will force kill>`); options.log(`[pid=${spawnedProcess.pid}] <will force kill>`);
// Force kill the browser. // Force kill the browser.
try { try {

View file

@ -124,15 +124,13 @@ export class WebServerPlugin implements TestRunnerPlugin {
if (!signal) if (!signal)
throw new Error('skip graceful shutdown'); throw new Error('skip graceful shutdown');
const success = launchedProcess.kill(signal); process.kill(-launchedProcess.pid!, signal);
if (!success)
throw new Error(`signal didn't succeed, fall back to non-graceful shutdown`);
return new Promise<void>((resolve, reject) => { return new Promise<void>((resolve, reject) => {
const timer = timeout !== 0 const timer = timeout !== 0
? setTimeout(() => reject(new Error(`process didn't close gracefully within timeout, falling back to SIGKILL`)), timeout) ? setTimeout(() => reject(new Error(`process didn't close gracefully within timeout, falling back to SIGKILL`)), timeout)
: undefined; : undefined;
launchedProcess.once('exit', () => { launchedProcess.once('close', (...args) => {
console.log("closing", ...args)
clearTimeout(timer); clearTimeout(timer);
resolve(); resolve();
}); });

View file

@ -9373,7 +9373,7 @@ interface TestConfigWebServer {
/** /**
* How to shut down the process gracefully. If unspecified, the process group is forcefully `SIGKILL`ed. If set to `{ * How to shut down the process gracefully. If unspecified, the process group is forcefully `SIGKILL`ed. If set to `{
* SIGINT: 500 }`, the top process is sent a `SIGINT` signal, followed by `SIGKILL` if it doesn't exit within 500ms. * SIGINT: 500 }`, the process group is sent a `SIGINT` signal, followed by `SIGKILL` if it doesn't exit within 500ms.
* You can also use `SIGTERM` instead. A `0` timeout means no `SIGKILL` will be sent. Windows doesn't support `SIGINT` * You can also use `SIGTERM` instead. A `0` timeout means no `SIGKILL` will be sent. Windows doesn't support `SIGINT`
* and `SIGTERM` signals, so this option is ignored. * and `SIGTERM` signals, so this option is ignored.
*/ */