Uh oh!
There was an error while loading. Please reload this page.
fix(chromium): re-issue Target.closeTarget when the target survives a racing navigation commit - #42367
Conversation
… racing navigation commit Chromium can acknowledge Target.closeTarget with success:true without actually closing the target: when the close races a navigation commit that swaps the main RenderFrameHost, the pending close request dies with the old frame host and the target never detaches, so page.close() hangs forever (https://issues.chromium.org/issues/536385539). Wait briefly for the page to close after Target.closeTarget and re-issue the close if the target is still alive. Also remove the stale fixme from the close-during-reload test: the rolled Chromium 152.0.7977.54 no longer loses the close in that scenario, and with the re-issue guard the close is robust either way. The guard chiefly protects channel builds (Chrome/Edge stable are on 151-class builds where the hang reproduces on ~70-80% of attempts with a meta-refresh trigger). Fixesmicrosoft#42068. References microsoft#42366. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Jeff Witt (wittjeff)
commented
Aug 22, 2026
@microsoft-github-policy-service agree [company="YRA Tech"] |
Jeff Witt (wittjeff)
commented
Aug 22, 2026
@microsoft-github-policy-service agree company="YRA Tech" |
Anton Petnitsky (Mukller)
commented
Aug 23, 2026
Nice find and clean fix. The retry loop handles the tricky parts correctly: registering the One thing worth making explicit before merge: if all 3 attempts time out (~3s), // Exhausting retries keeps the historical best-effort behavior of// _closePage; we deliberately do not throw here.(Optional nit: |
Devin Rousso (dcrousso)
commented
Aug 24, 2026
please see #41912 |
Fixes#42068. References #42366 and https://issues.chromium.org/issues/536385539.
The bug
Chromium can acknowledge
Target.closeTargetwithsuccess:truewithout actually closing the target: when the close races a navigation commit that swaps the main RenderFrameHost, the pending close request dies with the old frame host and is never re-issued (root-caused with code pointers in the crbug, which has a pending Chromium CL).Target.targetDestroyednever fires, sopage.close()awaitsclosedPromiseforever — no resolution, no rejection.The fix
In
CRBrowser._closePage, wait briefly (1 s) for the page to report closed afterTarget.closeTarget, and re-issue the close if the target is still alive (bounded at 3 attempts). Re-issuing reliably destroys such a target — verified over raw CDP as well as through Playwright. The normal path is unchanged: the close event resolves the wait immediately.Why a client-side guard when a Chromium CL is pending
channel: 'chrome'/'msedge'users are on 151-class stable builds where the hang reproduces on 7–8 of 10 attempts with a common real-world trigger — a page carrying<meta http-equiv="refresh" content="0; URL=...">closed right after the refresh commits (the W3C ACT-Rules bc659a "passed" fixtures are examples; we hit this scanning real pages, freezing long crawls for 35+ minutes with no error anywhere).closeTarget→success:true, notargetDestroyed, target still inTarget.getTargets) reproduces ~2/10 on 152 vs ~1-3/10 on 151. What changed in 152 is timing — through Playwright's call sequence the window has become hard to hit (0/10 in our runs), which is why no new test accompanies this PR: a race test that cannot reliably fail without the fix on the bundled browser would only be flaky. On 151-class builds the hang was near-deterministic through Playwright.Test changes
fixmefromshould close page while a reload is committing: it passes 6/6 repeats on the bundled 152 both with and without this change (the reload trigger no longer loses the close there), and with the guard it is robust on 151-class builds too, where it previously hung.tests/library/page-close.spec.ts,beforeunload.spec.ts, andbrowsercontext-pages.spec.tspass with the change (41/41).Verification matrix (10 rounds per cell, meta-refresh repro)
close()close({runBeforeUnload:true})context.close()🤖 Generated with Claude Code