Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/playwright-core/src/tools/dashboard/dashboardApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,9 @@ async function runKillClient(): Promise<void> {

async function runAnnotateClient(options: DashboardOptions): Promise<void> {
selfDestructOnParentGone();
// stdin is a pipe from the process that started this client. It emits 'close' only after it
// has been read to the end, so read it. Unref it, so that it does not keep the process alive.
process.stdin.resume().unref();

const socketPath = dashboardSocketPath();
const tryConnect = () => new Promise<net.Socket | undefined>(resolve => {
Expand Down
5 changes: 2 additions & 3 deletions packages/playwright-core/src/tools/utils/mcp/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,8 @@ function addServerListener(server: ServerType, event: 'close' | 'initialized', l
export async function start(serverBackendFactory: ServerBackendFactory, options: { host?: string; port?: number, allowedHosts?: string[], socketPath?: string } = {}) {
if (options.port === undefined) {
const transport = new StdioServerTransport();
// The SDK's StdioServerTransport doesn't detect peer disconnect — it never listens for stdin
// end-of-stream. Wire it up so callTool requests can be cancelled when the client goes away.
process.stdin.on('end', () => void transport.close());
// Do not close the transport on stdin end. The exit watchdog closes the browsers on stdin
// close, and closing a browser that is already closing force-kills it.
await connect(serverBackendFactory, transport, Promise.resolve(), false);
return;
}
Expand Down
20 changes: 20 additions & 0 deletions tests/mcp/launch.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,3 +317,23 @@ exit 1
error: expect.not.stringContaining(`Browser is already in use`),
});
});

test('should gracefully close the browser once on stdin end', {
annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/43098' }
}, async ({ startClient, server }, testInfo) => {
const { client, stderr } = await startClient({
args: [`--user-data-dir=${testInfo.outputPath('user-data-dir')}`],
env: { DEBUG: 'pw:browser' },
});
await client.callTool({
name: 'browser_navigate',
arguments: { url: server.HELLO_WORLD },
});

await client.close();

await expect.poll(() => stderr()).toContain('<gracefully close end>');
expect(stderr()).toContain('<gracefully close start>');
expect(stderr()).not.toContain('<forcefully close>');
expect(stderr()).not.toContain('<will force kill>');
});
Loading