cloudflare / cloudflare/workers-sdk

Miniflare Browser Rendering leaves all but the first Chrome orphaned on direct SIGINT

Open
#15,419 0 comments 0 reactions 0 assignees View on GitHub
product:browser
Dominant language
TypeScript
Stars
4.5k
Forks
1.5k
Avg merge
3d 8h
Merged PRs (30d)
187

Description

### What versions & operating system are you using?

```text
System:
OS: macOS 26.6.1 (25G76)
CPU: Apple Silicon (arm64)

Binaries:
Node: 26.7.0
pnpm: 11.11.0

Packages:
wrangler: 4.127.1
miniflare: 5.20260828.0-alpha
workerd: 1.20260828.1
@cloudflare/playwright: 1.3.0
```

I also originally observed the same behaviour with Wrangler 4.126.0 / Miniflare 5.20260825.0-alpha.

### Please provide a link to a minimal reproduction

https://gist.github.com/banchichen/e6ce9f82111ab32195b2af11d819d413

### Describe the Bug

When a local Browser Rendering worker has more than one Chrome session, sending `SIGINT` directly to the Wrangler Node process kills Wrangler and the first Chrome process tree, but leaves the remaining Chrome process tree orphaned.

Steps to reproduce:

1. Install and run the linked worker with `pnpm install && pnpm dev`.
2. Call it twice, at least one second apart, to acquire two Browser Rendering sessions.
3. Find the Wrangler Node process (the process running `wrangler-dist/cli.js dev`, not its `pnpm` parent).
4. Run `kill -INT `.
5. Inspect processes whose command contains `miniflare-.../browser-rendering`.

Before `SIGINT`, the two Chrome root processes in my Wrangler 4.127.1 run were:

```text
90046 89899 Ss .../Google Chrome for Testing .../browser-rendering/profile-42d0d8ed-...-0
90074 89899 Ss .../Google Chrome for Testing .../browser-rendering/profile-d85db5ca-...-0
```

Five seconds after `kill -INT 89899`, Wrangler and PID 90046 had exited, but the second Chrome was still alive and reparented to PID 1:

```text
90074 1 Ss .../Google Chrome for Testing .../browser-rendering/profile-d85db5ca-...-0
```

The same result was deterministic across repeated runs. Sending Ctrl-C through a package-manager PTY can take a different, graceful shutdown path, so the direct signal to the Wrangler Node process is important to the reproduction.

Expected behaviour: all Browser Rendering Chrome process trees exit when Wrangler receives `SIGINT`.

This appears to be a remaining edge case after the teardown work in #14727 / commit 3f3afbbf136c404d26ee39d187a44adb06c1b6e8. That change successfully cleans up normal sessions when Miniflare's centralized disposal completes, but direct `SIGINT` can bypass cleanup for all but the first session.

The likely cause is the interaction with `@puppeteer/browsers` signal handling:

- Browser Rendering currently passes `handleSIGTERM: false`, but leaves `handleSIGINT` at its default `true`: https://github.com/cloudflare/workers-sdk/blob/f8085545bcaa2c639f171c25e4424685036a0e10/packages/miniflare/src/plugins/browser-rendering/index.ts#L229-L232
- `@puppeteer/browsers` registers one `SIGINT` handler per launched `Process`. Its shared dispatcher iterates those handlers, but each handler kills its own browser and immediately calls `process.exit(130)`.
- Therefore the first browser handler exits the Wrangler process before later browser handlers can run, and before the centralized multi-browser teardown can complete.

One possible direction would be to disable per-browser `SIGINT` handling (and let Wrangler/Miniflare own shutdown for the full tracked set), plus add a multi-session direct-SIGINT regression test.

### Please provide any relevant error logs

Wrangler exits with status 130 as expected. There is no application error; the observable failure is the remaining Chrome process with `PPID 1`.

Contributor guide

Open the contributing guide

Research direction

Start in packages/miniflare/src/plugins/browser-rendering/index.ts at the handleSIGTERM/handleSIGINT options, then run the linked gist with two sessions and send SIGINT directly to the Wrangler Node process. Add a multi-session direct-SIGINT regression test and verify that all browser-rendering Chrome trees exit while Wrangler returns status 130.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, playwright, typescript
Domain
cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.