Skip to content

fix(tauri-runtime-cef): exit cleanly instead of panic when cef::initialize fails (TAURI-RUST-F)#17

Merged
senamakel merged 1 commit into
tinyhumansai:feat/ceffrom
oxoxDev:fix/tauri-rust-f-cef-init-graceful-exit
Jun 4, 2026
Merged

fix(tauri-runtime-cef): exit cleanly instead of panic when cef::initialize fails (TAURI-RUST-F)#17
senamakel merged 1 commit into
tinyhumansai:feat/ceffrom
oxoxDev:fix/tauri-rust-f-cef-init-graceful-exit

Conversation

@oxoxDev

@oxoxDev oxoxDev commented Jun 4, 2026

Copy link
Copy Markdown

What

CefRuntime::init asserted cef::initialize(...) == 1. On failure cef::initialize returns 0, so the assert fired panic: assertion \left == right` failed, left: 0, right: 1` — a fatal, actionless crash.

In the OpenHuman embedder this is Sentry TAURI-RUST-F (thousands of events across Windows, Linux and macOS). The dominant cause is a sequential relaunch race (auto-update relaunch / fast quit+reopen / restart flow) where a dying prior instance still holds the CEF user-data-dir cache lock; cef::initialize then returns 0. GPU / sandbox / permission failures hit the same assert.

Why here

init() is the single chokepoint every platform funnels through. init is a tauri_runtime::Runtime trait impl returning Self, so it cannot return Err without a trait change — but the failure is unrecoverable in-process anyway (no webview runtime), so the correct action is to inform the user and exit cleanly rather than panic.

Change

  • Replace assert_eq!(cef::initialize(...), 1) with if result != 1 { cef_init_guard::fail_cef_init_and_exit(result) }.
  • New cef_init_guard module: logs the failure, shows a best-effort native notice, then std::process::exit(0).
    • The dialog is wrapped in catch_unwind and the process always exits afterwards, so a misbehaving dialog backend can never re-introduce the panic.
    • Per-platform native dialog uses deps the crate already links: NSAlert (macOS), MessageBoxW (Windows), GtkMessageDialog (Linux). Adds only the cargo features needed (Win32_UI_WindowsAndMessaging, objc2-app-kit NSAlert/NSApplication, objc2-foundation NSString).

This prevents the panic structurally; it does not catch/suppress it — the assert is gone.

Test

  • cargo fmt / cargo check / cargo clippy clean on macOS (new module: zero warnings).
  • Happy path verified end-to-end in the OpenHuman shell: cef::initialize returns 1 → proceeds to RunEvent::Ready normally.
  • The Windows/Linux dialog glue is compiled out off-target; validated by CI build matrix (same constraint as the prior Windows-only guard).

Companion PR in the embedder adds a bounded macOS/Linux pre-CEF cache-lock wait so the common relaunch race resolves before init, with this as the universal backstop.

Summary by CodeRabbit

  • Bug Fixes
    • Improved startup failure handling: when runtime initialization fails the app now shows a native, platform-specific blocking error dialog (macOS, Windows, Linux/BSD) and then exits cleanly, instead of terminating abruptly. This gives clearer feedback and more graceful shutdown on startup errors.

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b9ebecbf-db00-4d6f-b8f5-06fc842eb442

📥 Commits

Reviewing files that changed from the base of the PR and between 334d55f and 98c7752.

📒 Files selected for processing (3)
  • crates/tauri-runtime-cef/Cargo.toml
  • crates/tauri-runtime-cef/src/cef_init_guard.rs
  • crates/tauri-runtime-cef/src/lib.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • crates/tauri-runtime-cef/Cargo.toml
  • crates/tauri-runtime-cef/src/cef_init_guard.rs

📝 Walkthrough

Walkthrough

This PR replaces a panic-on-failure CEF initialization path with a guarded handler that logs the failure, attempts a platform-native blocking notice (macOS NSAlert, Windows MessageBoxW, Linux GTK), and then exits the process cleanly.

Changes

CEF Initialization Guard

Layer / File(s) Summary
Dependency enablement for native dialogs
crates/tauri-runtime-cef/Cargo.toml
Windows target enables Win32_UI_WindowsAndMessaging for MessageBoxW; macOS target expands objc2-app-kit/objc2-foundation features for NSAlert/NSApplication/NSNotification/NSString support.
CEF init guard implementation with platform-specific dialogs
crates/tauri-runtime-cef/src/cef_init_guard.rs
New module fail_cef_init_and_exit() logs failure, wraps a platform-dispatching show_blocking_notice() in catch_unwind, shows NSAlert (macOS, main thread only), MessageBoxW (Windows), or GTK MessageDialog (Linux/BSD), then exits with code 0.
CEF initialization error handling integration
crates/tauri-runtime-cef/src/lib.rs
Declares cef_init_guard module and replaces assert_eq!(cef::initialize(...), 1) with logic that calls fail_cef_init_and_exit(init_result, &cache_path) on non-1 results.

Sequence Diagram(s)

sequenceDiagram
  participant CEF as CEF Runtime
  participant InitGuard as cef_init_guard::fail_cef_init_and_exit
  participant Dialog as Platform Dialog
  participant Proc as Process Exit

  CEF->>InitGuard: cef::initialize() returns non-1
  InitGuard->>InitGuard: log(init_result, cache_path)
  InitGuard->>Dialog: show_blocking_notice() (NSAlert / MessageBoxW / GTK)
  Dialog-->>InitGuard: dialog dismissed or error
  InitGuard->>Proc: exit(0)
Loading

🎯 3 (Moderate) | ⏱️ ~25 minutes

🐰 I hopped to warn, not shout,
When CEF trips and times run out.
A gentle box, a tiny bell,
Logs the tale and says farewell.
No panic — just a graceful rout. 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(tauri-runtime-cef): exit cleanly instead of panic when cef::initialize fails (TAURI-RUST-F)' accurately and clearly describes the main change: replacing a panic assertion with graceful exit when CEF initialization fails.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

…alize fails (TAURI-RUST-F)

cef::initialize() returns 1 on success and 0 on failure. The runtime
asserted the result equals 1, so any failure (a live prior instance
holding the CEF user-data-dir cache lock, or a GPU/sandbox/permission
failure) became a fatal 'panic: assertion left == right' with no
actionable message — Sentry TAURI-RUST-F, thousands of events across
Windows, Linux and macOS.

This is the single chokepoint every platform funnels through, so handle
the failure here: log the actual return code + cache_path (preserving
the Sentry-triage signal a panic used to give, via the stable
TAURI-RUST-F marker), show a best-effort native notice, and exit cleanly
(code 0) instead of asserting. The dialog is wrapped in catch_unwind and
the process always exits afterwards, so a misbehaving dialog backend can
never re-introduce the crash. Per-platform native dialog uses deps the
crate already links (NSAlert / MessageBoxW / GtkMessageDialog).

Supersedes the diagnostic-panic approach of tinyhumansai#13 (orphaned when its
companion openhuman#1510 merged without the bump): a still-fatal panic
does not meet the 'no recurrence' bar now that TAURI-RUST-F is frequent
and cross-platform; this keeps the diagnostic context but removes the
crash.
@oxoxDev oxoxDev force-pushed the fix/tauri-rust-f-cef-init-graceful-exit branch from 334d55f to 98c7752 Compare June 4, 2026 10:18
@oxoxDev

oxoxDev commented Jun 4, 2026

Copy link
Copy Markdown
Author

@senamakel — flagging overlap with your #13 (same line, CefRuntime::init assert), and folding in its intent.

History as I read it:

Why supersede rather than revive #13:

  • The single-instance plugin handles the concurrent race, but TAURI-RUST-F is the sequential relaunch race — the dying primary's CEF child still holds the cache lock after the mutex/socket is released. tauri-plugin-single-instance doesn't cover it (hence the later Windows-only openhuman#3210).
  • It's still firing ~3.4k events across Windows + Linux + macOS on the post-[bug] create-tauri-app, svelte, default port 5000 unmatch with the rollup default 8080 tauri-apps/tauri#3210 release 0.57.13. A still-fatal panic (even a well-labelled one) doesn't meet the "no recurrence" bar the maintainer asked for here.

What this PR keeps from #13: the actionable diagnostic — the pre-exit log::error! carries the actual cef::initialize return code and cache_path plus a stable TAURI-RUST-F marker, so the Sentry-triage signal survives. It just exits cleanly (code 0) + shows a best-effort native notice instead of crashing. Dialog is catch_unwind-wrapped with an unconditional exit(0), so it can never re-introduce a panic.

Companion openhuman PR (tauri-apps#3337) adds a bounded macOS/Linux pre-CEF cache-lock wait so the common relaunch race resolves before init, with this as the universal backstop.

Happy to defer to your preference on the line — does graceful-exit-with-diagnostics work for you, or do you want to keep the panic-as-Sentry-signal? Can close #13 if this lands.

@senamakel senamakel merged commit 8ea806e into tinyhumansai:feat/cef Jun 4, 2026
1 check 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