diff --git a/packages/playwright-core/src/utils/processLauncher.ts b/packages/playwright-core/src/utils/processLauncher.ts index 62219e286c..4e6c1030b2 100644 --- a/packages/playwright-core/src/utils/processLauncher.ts +++ b/packages/playwright-core/src/utils/processLauncher.ts @@ -121,6 +121,13 @@ function addProcessHandlerIfNeeded(name: 'exit' | 'SIGINT' | 'SIGTERM' | 'SIGHUP process.on(name, processHandlers[name]); } } +function removeProcessHandlersIfNeeded() { + if (killSet.size) + return; + for (const handler of installedHandlers) + process.off(handler, processHandlers[handler]); + installedHandlers.clear(); +} export async function launchProcess(options: LaunchProcessOptions): Promise { const stdio: ('ignore' | 'pipe')[] = options.stdio === 'pipe' ? ['ignore', 'pipe', 'pipe', 'pipe', 'pipe'] : ['pipe', 'pipe', 'pipe']; @@ -178,6 +185,7 @@ export async function launchProcess(options: LaunchProcessOptions): Promise`); if (spawnedProcess.pid && !spawnedProcess.killed && !processClosed) { options.log(`[pid=${spawnedProcess.pid}] `); diff --git a/tests/config/remote-server-impl.js b/tests/config/remote-server-impl.js index 33532321f0..baf6d946b9 100644 --- a/tests/config/remote-server-impl.js +++ b/tests/config/remote-server-impl.js @@ -2,7 +2,7 @@ const fs = require('fs'); const cluster = require('cluster'); async function start() { - const { browserTypeName, launchOptions, stallOnClose, disconnectOnSIGHUP, exitOnFile, exitOnWarning } = JSON.parse(process.argv[2]); + const { browserTypeName, launchOptions, stallOnClose, disconnectOnSIGHUP, exitOnFile, exitOnWarning, startStopAndRunHttp } = JSON.parse(process.argv[2]); if (stallOnClose) { launchOptions.__testHookGracefullyClose = () => { console.log(`(stalled=>true)`); @@ -11,11 +11,20 @@ async function start() { } if (exitOnWarning) process.on('warning', () => process.exit(43)); + if (disconnectOnSIGHUP) + launchOptions.handleSIGHUP = false; const playwright = require('playwright-core'); - if (disconnectOnSIGHUP) - launchOptions.handleSIGHUP = false; + if (startStopAndRunHttp) { + const browser = await playwright[browserTypeName].launch(launchOptions); + await browser.close(); + console.log(`(wsEndpoint=>none)`); + console.log(`(closed=>success)`); + require('http').createServer(() => {}).listen(); + return; + } + const browserServer = await playwright[browserTypeName].launchServer(launchOptions); if (disconnectOnSIGHUP) process.on('SIGHUP', () => browserServer._disconnectForTest()); diff --git a/tests/config/remoteServer.ts b/tests/config/remoteServer.ts index 39c6e1aa25..05ddae2179 100644 --- a/tests/config/remoteServer.ts +++ b/tests/config/remoteServer.ts @@ -68,6 +68,7 @@ export type RemoteServerOptions = { exitOnWarning?: boolean; inCluster?: boolean; url?: string; + startStopAndRunHttp?: boolean; }; export class RemoteServer implements PlaywrightServer { @@ -150,6 +151,10 @@ export class RemoteServer implements PlaywrightServer { return await this._process.exitCode; } + async childSignal() { + return (await this._process.exited).signal; + } + async close() { if (this._browser) { await this._browser.close(); diff --git a/tests/library/signals.spec.ts b/tests/library/signals.spec.ts index 6ae54cfd3c..232db694f3 100644 --- a/tests/library/signals.spec.ts +++ b/tests/library/signals.spec.ts @@ -133,4 +133,12 @@ test.describe('signals', () => { expect(await remoteServer.out('signal')).toBe('SIGKILL'); expect(await remoteServer.childExitCode()).toBe(130); }); + + test('should not prevent default SIGTERM handling after browser close', async ({ startRemoteServer, server, platform }, testInfo) => { + const remoteServer = await startRemoteServer('launchServer', { startStopAndRunHttp: true }); + expect(await remoteServer.out('closed')).toBe('success'); + process.kill(remoteServer.child().pid, 'SIGTERM'); + expect(await remoteServer.childExitCode()).toBe(null); + expect(await remoteServer.childSignal()).toBe('SIGTERM'); + }); });