Skip to content

fix(tauri): resolve Linux CEF init panic — root/container + SingletonLock + display-server guards (OPENHUMAN-TAURI-K1)#2103

Merged
senamakel merged 6 commits into
tinyhumansai:mainfrom
YellowSnnowmann:fix/sentry-OPENHUMAN-TAURI-K1
May 19, 2026
Merged

fix(tauri): resolve Linux CEF init panic — root/container + SingletonLock + display-server guards (OPENHUMAN-TAURI-K1)#2103
senamakel merged 6 commits into
tinyhumansai:mainfrom
YellowSnnowmann:fix/sentry-OPENHUMAN-TAURI-K1

Conversation

@YellowSnnowmann
Copy link
Copy Markdown
Contributor

@YellowSnnowmann YellowSnnowmann commented May 18, 2026

Summary

  • Fixes fatal Linux startup panic: `assertion left == right failed` (left: 0, right: 1) in `tauri_runtime_cef::CefRuntime::init`
  • Adds `--no-sandbox` CLI flag to CEF when running as root (uid=0) — dominant cause per Sentry trace (coder-bot/CI containers)
  • Adds display-server pre-flight guard: exits cleanly when `DISPLAY` and `WAYLAND_DISPLAY` are both unset (WSL2/headless)
  • Extends macOS SingletonLock preflight check to Linux (XDG cache path, same `cef_initialize → 0` failure mode)

Problem

Sentry OPENHUMAN-TAURI-K1 reports 55 fatal panics on Linux. The crash is in `CefRuntime::init` where `cef::initialize()` returns 0 and the vendored runtime asserts it equals 1. The Sentry breadcrumbs show the process runs as root under `/root/.hermes/profiles/coder-bot/home` — a CI/container environment. Chromium's browser process silently rejects root unless `--no-sandbox` is on the command line; `Settings.no_sandbox = 1` only disables sub-process sandboxing.

Solution

  • Detect `uid == 0` via `nix::unistd::getuid()` in `append_platform_cef_gpu_workarounds` (Linux only, cfg-gated) and append `--no-sandbox`
  • Add `check_linux_display_server()` that runs before `Builder::build` and exits with a clear message when no display server is present
  • Extend `cef_preflight::check_default_cache` to Linux: `OPENHUMAN_CEF_CACHE_PATH` → `$XDG_CACHE_HOME//cef` → `$HOME/.cache//cef` fallback chain matching `dirs::cache_dir()`

Windows and macOS are unaffected — all new Linux paths are `#[cfg(target_os = "linux")]`.

Submission Checklist

If a section does not apply to this change, mark the item as `N/A` with a one-line reason. Do not delete items.

  • Tests added or updated (happy path + at least one failure / edge case) per Testing Strategy
  • Diff coverage ≥ 80% — changed lines (Vitest + cargo-llvm-cov merged via `diff-cover`) meet the gate enforced by .github/workflows/coverage.yml. Run `pnpm test:coverage` and `pnpm test:rust` locally; PRs below 80% on changed lines will not merge.
  • N/A: Coverage matrix updated — no new feature rows; this is a bug fix for an existing startup path
  • N/A: All affected feature IDs from the matrix are listed — no matrix feature IDs apply to CEF init guards
  • No new external network dependencies introduced (mock backend used per Testing Strategy)
  • N/A: Manual smoke checklist updated — no release-cut surfaces touched
  • Linked issue closed via `Closes #NNN` in the `## Related` section

Impact

  • Linux only. Resolves fatal crash on startup in root/container environments (CI, coder-bot, Docker).
  • No behavioural change for non-root Linux users or macOS/Windows users.
  • `nix` dependency gains the `user` feature (needed for `getuid()`).

Related


AI Authored PR Metadata (required for Codex/Linear PRs)

Keep this section for AI-authored PRs. For human-only PRs, mark each field `N/A`.

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: `fix/sentry-OPENHUMAN-TAURI-K1`
  • Commit SHA: `26c5b41d`

Validation Run

  • `pnpm --filter openhuman-app format:check`
  • `pnpm typecheck`
  • Focused tests: `cargo test --manifest-path app/src-tauri/Cargo.toml -- linux cef_preflight` — 17 passed
  • Rust fmt/check (if changed): `cargo check --manifest-path app/src-tauri/Cargo.toml` — clean
  • Tauri fmt/check (if changed): clean

Validation Blocked

  • `command:` N/A
  • `error:` N/A
  • `impact:` N/A

Behavior Changes

  • Intended behavior change: CEF on Linux now starts successfully when running as root; exits cleanly with actionable message when no display server is available
  • User-visible effect: App launches in CI/container environments instead of panicking with an opaque Rust backtrace

Parity Contract

  • Legacy behavior preserved: non-root Linux, macOS, and Windows paths are unchanged
  • Guard/fallback/dispatch parity checks: `#[cfg(target_os = "linux")]` gates ensure zero code generation on other platforms

Duplicate / Superseded PR Handling

  • Duplicate PR(s): N/A
  • Canonical PR: this one
  • Resolution (closed/superseded/updated): N/A

Summary by CodeRabbit

  • Bug Fixes

    • Added display-server validation on Linux with clear startup messaging when unavailable.
    • Extended CEF cache preflight and platform-specific cache path handling to Linux and macOS, honoring environment override.
    • Improved sandbox handling when running with elevated privileges.
  • Tests

    • Serialized env-var tests to avoid race conditions and added coverage for new Linux helpers and cache behavior.

Review Change Stack

…-K1)

The SingletonLock check that catches concurrent-launch panics on macOS
(issue tinyhumansai#864) was gated to `#[cfg(target_os = "macos")]`. The same panic
fires on Linux when a second instance races `cef_initialize` and finds
the SingletonLock already held.

Extend `cef_preflight`:
- `mod cef_preflight` now compiled on `any(macos, linux)`
- `check_default_cache` gains a Linux path: honours
  `OPENHUMAN_CEF_CACHE_PATH` first (always set by
  `cef_profile::prepare_process_cache_path` before this runs), then
  falls back to `$XDG_CACHE_HOME/<id>/cef` or `$HOME/.cache/<id>/cef`
  matching the `dirs::cache_dir()` fallback used by tauri-runtime-cef

New tests:
- `check_default_cache_uses_configured_env_path` — env-path no-lock
- `check_default_cache_env_path_held_returns_err` — env-path held
- `check_default_cache_linux_xdg_fallback_no_lock` — Linux XDG fallback
…I-K1)

CEF requires a display server (X11 or Wayland) to initialise. On WSL2
without WSLg, and on headless Linux boxes, both DISPLAY and
WAYLAND_DISPLAY are unset. In that case `cef_initialize` returns 0 and
the vendored `tauri-runtime-cef` assertion fires (`left: 0, right: 1`)
— a fatal, silent panic with no actionable error message.

Adds `check_linux_display_server()` that runs before the Tauri builder
(before `CefRuntime::init`) on Linux only:
- If either DISPLAY or WAYLAND_DISPLAY is set → no-op, continue
- If both are absent → log an error, print a human-readable message
  with WSL2 guidance, and exit(1) cleanly

Also extends the preflight call site from `#[cfg(macos)]` to
`#[cfg(any(macos, linux))]` so the SingletonLock check from commit
021b069 is wired in on Linux too.

Mirrors the Windows pre-CEF single-instance guard pattern from tinyhumansai#1723.
…ards

- linux_display_present_with_{x11,wayland,both}: verify pure fn
- linux_display_absent_without_either: no-display → false

cef_preflight tests (check_default_cache_*):
- uses_configured_env_path: OPENHUMAN_CEF_CACHE_PATH no-lock → Ok
- env_path_held_returns_err: env-path with live lock → CefLockError::Held
- linux_xdg_fallback_no_lock (#[cfg(linux)]): XDG_CACHE_HOME redirect,
  no lock → Ok
…PENHUMAN-TAURI-K1)

Sentry trace shows the panic originates in environments running as root
(uid=0) under `/root/.hermes/profiles/coder-bot/home` — CI / coder-bot
/ Docker containers. The display server was present (Xvfb), so the
earlier display-server check does not fire. The issue is Chromium's
browser-process root-user check: `cef::initialize` returns 0 unless
`--no-sandbox` is passed on the command line. The `no_sandbox: 1` field
in `cef::Settings` disables the sub-process sandbox but does NOT satisfy
this separate root-user guard.

Fix: in `append_platform_cef_gpu_workarounds`, detect `uid == 0` via
`nix::unistd::getuid()` (already a dependency) and append `--no-sandbox`
to the CEF command-line args. No-op on non-root users and on
Windows/macOS (cfg-gated).

Also adds the `user` feature to the `nix` dependency (needed for
`getuid()`; previously only `signal` was enabled).

Tests:
- linux_root_uid_detected: uid 0 → true
- linux_non_root_uid_not_detected: uid 1000/1 → false
@YellowSnnowmann YellowSnnowmann requested a review from a team May 18, 2026 12:29
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 18, 2026

📝 Walkthrough

Walkthrough

This PR extends CEF startup safety to Linux: platform-aware cache directory resolution (with env override), display-server presence checks that exit early when missing, root-UID detection that adds --no-sandbox, expanded cache-lock preflight to Linux, and removal of the unused nix "user" feature.

Changes

Linux CEF Initialization Safety

Layer / File(s) Summary
CEF cache directory resolution for Linux and macOS
app/src-tauri/src/cef_preflight.rs
Module and function docs updated; check_default_cache prefers OPENHUMAN_CEF_CACHE_PATH, then macOS ~/Library/Caches/<ID>/cef, or Linux $XDG_CACHE_HOME/<ID>/cef when absolute with fallback to $HOME/.cache/<ID>/cef. Tests added/updated and a module ENV_LOCK mutex serializes env-mutating tests.
Linux display-server and UID helpers
app/src-tauri/src/lib.rs
Adds linux_display_server_present predicate, check_linux_display_server() (Linux-only early-exit), and linux_is_root_uid predicate with unit tests for display-server and UID cases.
CEF argument wiring, preflight gating, and dependency change
app/src-tauri/src/lib.rs, app/src-tauri/Cargo.toml
Calls check_linux_display_server() early in run(). Appends --no-sandbox to CEF CLI args when running as UID 0. Expands CEF cache-lock collision preflight gating to include Linux. Removes the "user" feature from the nix dependency under cfg(unix).

Sequence Diagram

sequenceDiagram
  participant Startup as Startup (run)
  participant DisplayCheck as Display Server Check
  participant UIDCheck as UID Detection
  participant CacheResolution as Cache Resolution
  participant CEF as CEF Initialize
  
  Startup->>DisplayCheck: check_linux_display_server()
  DisplayCheck->>Startup: DISPLAY or WAYLAND_DISPLAY present?
  alt Display server missing
    DisplayCheck->>Startup: Exit with error message
    Startup-->>CEF: Abort
  end
  
  Startup->>UIDCheck: Check process UID
  UIDCheck->>UIDCheck: UID == 0?
  alt Root detected
    UIDCheck->>Startup: Append --no-sandbox to CEF args
  end
  
  Startup->>CacheResolution: Resolve cache directory (env or platform default)
  CacheResolution->>Startup: Return cache path
  Startup->>Startup: Check cache singleton lock
  Startup->>CEF: Initialize with flags & cache path
  CEF->>CEF: Run
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped through code on Linux nights,
I checked DISPLAY, WAYLAND, and cache delights.
If no server's found, I politely flee,
And if I'm root, sandbox says let me be—
Safe start, snug app, now hop with me!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main changes: fixing a Linux CEF initialization panic by adding root/container detection, SingletonLock checks, and display-server guards.
Linked Issues check ✅ Passed All coding objectives from issue #2078 are implemented: pre-flight CEF validation, root detection with --no-sandbox flag, display-server checks, cache-lock verification for Linux, and comprehensive test coverage.
Out of Scope Changes check ✅ Passed All changes directly support the stated objectives: nix dependency for uid detection, cef_preflight Linux support, lib.rs Linux startup guards, and tests for new functionality—no unrelated modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src-tauri/src/cef_preflight.rs`:
- Around line 342-419: Tests create per-function local static ENV_LOCKs causing
races; replace them with a single shared module-level lock. Remove the local
`static ENV_LOCK: std::sync::Mutex<()> = ...` declarations in the tests and add
one shared `static ENV_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());`
(or use once_cell::sync::Lazy if needed) at module scope, then keep the existing
lock acquisition lines (`let _guard = ENV_LOCK.lock().unwrap_or_else(|e|
e.into_inner());`) in each test (e.g., check_default_cache_env_path_no_lock,
check_default_cache_env_path_held_returns_err,
check_default_cache_linux_xdg_fallback_no_lock) so all tests serialize access to
process-wide environment mutation.

In `@app/src-tauri/src/lib.rs`:
- Around line 1680-1690: The helper append_platform_cef_gpu_workarounds
currently pushes "--no-sandbox" when running as root using a cfg(target_os =
"linux") block, but that lets the flag be added even when the helper is invoked
with a non-Linux os string; update append_platform_cef_gpu_workarounds to only
append the "--no-sandbox" tuple when the provided os parameter equals "linux"
(e.g., if os == "linux") and then perform the root check (call
linux_is_root_uid()) inside that conditional; reference the function
append_platform_cef_gpu_workarounds, the helper linux_is_root_uid, and the
args.push(("--no-sandbox", None)) site so the flag only gets added for Linux
runs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a446aaa6-3a85-4d0c-887a-8bdd281335e6

📥 Commits

Reviewing files that changed from the base of the PR and between 70fdedc and 26c5b41.

📒 Files selected for processing (3)
  • app/src-tauri/Cargo.toml
  • app/src-tauri/src/cef_preflight.rs
  • app/src-tauri/src/lib.rs

Comment thread app/src-tauri/src/cef_preflight.rs Outdated
Comment thread app/src-tauri/src/lib.rs
… on os param

- cef_preflight: replace per-test local static ENV_LOCK with a single
  module-level static so all env-mutating tests are serialised and
  cannot race (CodeRabbit suggestion)
- lib.rs: add `os == "linux"` guard inside the #[cfg(linux)] block in
  append_platform_cef_gpu_workarounds so --no-sandbox is only appended
  when the os param matches, not just the compile-time target
  (CodeRabbit suggestion)
@senamakel senamakel merged commit 868ad8d into tinyhumansai:main May 19, 2026
36 of 38 checks passed
CodeGhost21 pushed a commit to CodeGhost21/openhuman that referenced this pull request May 22, 2026
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.

fix(tauri): panic in CefRuntime::init assertion failure on Linux

2 participants