Skip to content

[Bug]: Desktop app can still crash when a preview tab's renderer dies mid-screenshot, until Electron ships Chromium 157 #24094

Open

Description

@shivamhwp

[Opus 5.5][Claude Code] on behalf of shivam.

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/desktop

What happened

#24026 reported the desktop app crashing (SIGSEGV at 0x0 in the main process) when a preview tab's renderer died while an agent was taking a snapshot of it. The cause is a Chromium bug, not T3 code:

  • An agent snapshot ends in a CDP Page.captureScreenshot on the guest. Chromium copies the tab's surface for it.
  • If the guest's renderer dies while that copy is in flight, the copy fails. RenderWidgetHostImpl::OnSnapshotFromSurfaceReceived retries through GetView()->CopyFromSurface without checking GetView(), which is null once the renderer is gone. PageHandler::ScreenshotCaptured has the same unchecked GetView() when a clip is set, and our snapshots send a clip when they downscale.
  • Chromium fixed both in 157: crbug.com/567321049, commit f49f3e5. We ship Electron 44.9.3, and the newest stable Electron (45.0.0) is on Chromium 156, so every build today can hit it.

I reproduced it on Linux with Electron 44.9.3. A harness loaded the real DesktopBrowserHost.ts into Electron, kept agent screenshots in flight, and SIGKILLed the guest renderer. The crash symbolicated to the same frame as #24026.

What #24056 changed, and why it isn't the whole fix

T3 made the crash much likelier than it needed to be. A guest could have several screenshots copying at once, because snapshots overlapped and because a snapshot the server timed out on keeps running inside Chromium (CDP commands can't be cancelled). Every copy in flight is another chance to be mid-copy when the renderer dies.

#24056 sends each guest one screenshot at a time. The queue moves on when the page navigates or reloads, since a pending capture can go unanswered across a new document, and screenshots left by a released relay are dropped. In the stress harness, crashes per renderer kill went from 9 of 32 (about 28%) on main to 20 of 774 (about 2.6%), and the rate rises with machine load.

One copy can still be in flight when a renderer dies, so the crash is rarer but still possible. That's what this issue tracks.

Expected behavior

A preview tab whose renderer dies during a snapshot reports a crashed tab, and the app keeps running.

Actual behavior

Since #24056 this is rarer, but the desktop main process can still segfault, taking the bundled server with it.

What would fully fix it

Either one:

  1. Bump apps/desktop to an Electron release on Chromium 157 or newer once one is stable.
  2. Ask Electron to backport f49f3e5 to the 44-x-y and 45-x-y branches, then take that patch release.

Once Electron has the fix, the one-at-a-time queue in DesktopBrowserHost.ts can stay, since it keeps abandoned captures from piling up, or it can go.

Impact

Minor bug or occasional failure

Version or commit

main at cccb78c, after #24056 (Electron 44.9.3)

Environment

Desktop app. Reproduced on Linux (Xvfb, Electron 44.9.3); originally reported on macOS arm64 (Electron 44.4.5).

Workaround

None in the app. Agents taking fewer snapshots of a page that is about to run out of memory makes it less likely.

Activity

  1. added
    bugSomething is broken or behaving incorrectly.
    needs-triageIssue needs maintainer review and initial categorization.
    on Oct 23, 2026
  2. SKCarlsson commented on Oct 24, 2026

    @SKCarlsson

    [Opus 5.5][Claude Code] on behalf of SKCarlsson.

    Hit again on macOS with #24056 included. The evidence suggests the capture that crashed the app had been stuck for about a day, so the risk lasts longer than "while a screenshot is in flight".

    The crash

    CrBrowserMain  EXC_BAD_ACCESS (SIGSEGV) KERN_INVALID_ADDRESS at 0x0
    #0 content::RenderWidgetHostImpl::OnSnapshotFromSurfaceReceived   render_widget_host_impl.cc:3917
    #1 RenderWidgetHostViewChildFrame::CopyFromSurface(...)::$_0      (callback)
    #3 base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork()
    #6 base::MessagePumpCFRunLoopBase::RunWorkSource(void*)
    

    The faulting instruction is ldr x8, [x21] with x21 = 0 (the null GetView()), followed by a vtable call.

    No screenshot was being taken

    The retained server traces cover the ~50 minutes before the crash and contain no preview automation calls. The only preview spans are PreviewAutomationBroker.focusHost and PreviewManager.close at 21:05:51.65, after the main process had already died.

    The pending capture was probably ~26 hours old

    macOS powerd shows the main process holding a "Capturing" NoDisplaySleepAssertion for the whole session:

    2026-10-23 19:28:53  preview guest renderer starts (pid 9439, surface "preview" in renderer-history.ndjson)
    2026-10-23 19:29:04  powerd: Created NoDisplaySleepAssertion "Capturing"  id:21474876784
    2026-10-24 21:02:21  guest renderer 9439 still alive (last renderer-history sample)
    2026-10-24 21:05:51  main process SIGSEGV
    2026-10-24 21:05:51  powerd: ClientDied NoDisplaySleepAssertion "Capturing"  age:25:36:46
    

    In Chromium 152 the only DevTools path that takes this lock is Page.captureScreenshot: IncrementCapturerCount(stay_awake=true) at page_handler.cc:1432. The handle lives in PendingScreenshotRequest until the snapshot callback runs. Page.startScreencast takes no capturer handle, and neither does DevToolsVideoConsumer. Outside DevTools, a tab-capture stream (the getDisplayMedia recording path) holds the same lock. A lock held for 25.6 hours plus a crash in the screenshot callback with no screenshot requested points to one Page.captureScreenshot that stalled on 2026-10-23 and stayed pending until the guest's renderer went away. The desktop and server traces from 19:29 on 2026-10-23 have already rotated out, so I couldn't see which call started it.

    What this means for this issue

    I couldn't see what ended the guest renderer at 21:05:51 because macOS doesn't log renderer exits. A T3 utility helper exited and T3's audio session stopped about 100 ms before the main process died.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is broken or behaving incorrectly.needs-triageIssue needs maintainer review and initial categorization.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions