Skip to content

fix(linux): prevent browser teardown from disabling WebGL - #166

Merged
maddada merged 1 commit into
maddada:mainfrom
alp82:fix/linux-webgl-browser-teardown
Sep 27, 2026
Merged

maddada merged 1 commit into
maddada:mainfrom
alp82:fix/linux-webgl-browser-teardown

Conversation

@alp82

@alp82 alp82 commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Closing an embedded browser could destroy its X11 parent while Chromium was still creating a GPU surface. On the affected Linux machine, ANGLE crashed in WindowSurfaceGLX::initialize after XGetWindowAttributes returned no visual; Chromium recorded three GPU crashes and disabled WebGL for every tab.

Keep the embed host alive but unmapped and reparented away from its GPUI owner during close. Allow CEF to perform its native X11 child close, then release the embed host from on_before_close. This fixes the window lifetime in the desktop CEF adapter without changing GPU flags or introducing software rendering.

Validation:

  • cargo check --bin ghostex-gpui --offline passed on Linux (existing warnings).
  • Formatting and git diff --check passed.
  • The reporter confirmed the fix works in the embedded browser.
  • macOS and Windows runtime behavior was not tested; their close paths are unchanged.

Note

Fix Linux browser teardown destroying WebGL embed host too early

  • On Linux, release_native_view now only unmaps and reparents the embed host to the X11 root window instead of destroying it (linux_x11.rs)
  • Adds browser_native_close_finished, which destroys and flushes the host after CEF finishes closing the browser
  • LifeSpanHandler::do_close now marks app-initiated closes as handled on Linux, and on_before_close calls the new cleanup after unregistering the native view (browser_handlers.rs)
  • Risk: Linux close ordering changes — host destruction now depends on on_before_close firing; check browser_native_close_finished and the do_close handled-close branch if browser windows linger

Macroscope summarized 8e97109.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed an issue on Linux where closing a browser window could leave its embedded view in an inconsistent state. Browser views now detach and close in the correct order.

@coderabbitai

coderabbitai Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 6dde67a7-505c-4e93-85de-6edae87289b6

📥 Commits

Reviewing files that changed from the base of the PR and between 566380b and 8e97109.

📒 Files selected for processing (3)
  • apps/desktop/src/cef/linux_x11.rs
  • apps/desktop/src/cef/shell/browser.rs
  • apps/desktop/src/cef/shell/browser_handlers.rs

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review.


📝 Walkthrough

Walkthrough

Linux CEF close handling now allows native closing to proceed in specified cases. Native-view release detaches the embed host, and the close callback notifies Linux after unregistering the browser.

Changes

Linux CEF close lifecycle

Layer / File(s) Summary
Allow CEF native close
apps/desktop/src/cef/shell/browser_handlers.rs
On Linux, do_close returns unhandled for app-initiated closes or browsers configured to register a created native view. The teardown comment distinguishes Linux behavior from macOS and Windows.
Detach and finish native-view teardown
apps/desktop/src/cef/linux_x11.rs, apps/desktop/src/cef/shell/browser.rs, apps/desktop/src/cef/shell/browser_handlers.rs
Native-view release unmaps and reparents the embed host, then waits for an X11 server round-trip. The comments describe the close order. on_before_close notifies Linux after unregistering the browser.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~15 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant CEF
  participant do_close
  participant CefBrowser_drop
  participant linux_x11_release_native_view
  participant X11_server
  participant on_before_close
  participant browser_native_close_finished
  CEF->>do_close: Request close
  do_close-->>CEF: Return 0 for applicable Linux closes
  CefBrowser_drop->>linux_x11_release_native_view: Release native view
  linux_x11_release_native_view->>X11_server: Unmap and reparent embed host
  linux_x11_release_native_view->>X11_server: Wait for server round-trip
  CEF->>CEF: Close X11 child
  CEF->>on_before_close: Finish native close
  on_before_close->>browser_native_close_finished: Notify native close finished
Loading

Suggested reviewers: maddada

Merge Risk: ⚪ Minimal · up to 8e971

No confirmed issue remains that should block merging. The native handle’s value during the close callback has not been verified.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 8e971

The change addresses a browser-close race that could disable WebGL across tabs. The normal close path preserves per-browser window identity, but cleanup now depends on completion of an asynchronous callback. No new attacker-controlled access path or verified security finding was established.

Retained concerns

  • Low · reliability · inferred: Embed-host cleanup is now conditional on reaching on_before_close. If a close is interrupted before that callback, the detached X11 host and its registry entry have no identified fallback cleanup path, weakening failure containment.
Security review details

Security Blast Radius

  • inferred — The observed X11 operations are scoped to the host associated with the closing browser's native handle. The motivating GPU failure has a wider, cross-tab WebGL consequence; the reviewed change aims to avoid that shared-process outcome.

Trust Boundaries and Controls

  • inferred — Both release and callback cleanup derive an X11 ID from the specific CEF browser handle and use the per-window registry; the inspected close path does not show a page-supplied handle crossing into these operations.

Resilience and Maintainability Implications

  • inferred — Removing the registry entry before destroying the host makes ordinary repeated cleanup locally harmless. The code does not establish callback delivery during interrupted teardown or protection against a delayed callback after X11 ID reuse.

Hardening Proposals

  • proposed — Establish the CEF callback-delivery guarantee for Linux shutdown and failed closes, or provide bounded cleanup for hosts left detached without a callback. Verify X11 reparent failure handling and delayed-callback identity before relying on this transition for failure containment.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 3 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main Linux browser teardown fix and its WebGL-related purpose.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

Warning

Some tools did not complete. Review the errors below.

🔧 Clippy (1.98.1)

Clippy execution failed


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@maddada
maddada merged commit a13294d into maddada:main Sep 27, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants