Skip to content

fix(linux): resolve startup hang caused by Webview log target deadlock#150

Merged
dannysmith merged 2 commits intodannysmith:mainfrom
MareDevi:fix/linux-startup-hang
Mar 12, 2026
Merged

fix(linux): resolve startup hang caused by Webview log target deadlock#150
dannysmith merged 2 commits intodannysmith:mainfrom
MareDevi:fix/linux-startup-hang

Conversation

@MareDevi
Copy link
Copy Markdown
Contributor

@MareDevi MareDevi commented Mar 10, 2026

Problem

On Linux (tested on Arch Linux with Wayland + WebKitGTK), running pnpm run tauri dev hangs permanently after:

[INFO] Astro Editor v1.0.10 starting up
[mio::poll][TRACE] registering event source with poller: token=Token(1), interests=READABLE

The app window never appears. The same hang occurs with cargo run directly.

Root Cause

Two separate issues, both Linux-specific:

1. tauri_plugin_log Webview target deadlock (lib.rs)

The Webview log target calls app.emit() internally on every log::info! call. During setup(), the WebKitGTK webview process does not yet exist. On Linux, this causes the underlying IPC socket to be registered with mio (Token(1), interests=READABLE) with no peer to write to it — the epoll event never fires and setup() blocks forever.

This was confirmed by bisecting with eprintln! checkpoints: execution stops inside the first log::info! call and never returns.

On macOS the webview initialisation order is different and this path is safe.

2. macos-private-api in base [dependencies] (Cargo.toml)

tauri-build validates that the macos-private-api Cargo feature matches "macOSPrivateApi": true in the merged tauri.conf.json. On macOS, tauri.macos.conf.json is merged in at build time and supplies that key. On Linux only tauri.conf.json + tauri.linux.conf.json are merged — neither contains macOSPrivateApi — so the build fails with:

The `tauri` dependency features on the `Cargo.toml` file does not match the allowlist defined under `tauri.conf.json`.

The existing comment states this feature is "a no-op on non-macOS", but tauri-build's validation fires regardless of platform.

Fix

src-tauri/src/lib.rs — restrict the Webview log target to macOS only using #[cfg(target_os = "macos")]. Stdout and LogDir targets continue to work on all platforms.

src-tauri/Cargo.toml — move macos-private-api from the base [dependencies] into [target.'cfg(target_os = "macos")'.dependencies]. Cargo merges features across sections, so macOS builds retain the full feature set (protocol-asset + macos-private-api) while Linux/Windows builds only get protocol-asset, satisfying tauri-build on both platforms.

Testing

Verified on Arch Linux (Wayland, WebKitGTK 4.1 + 6.0). The app now starts up fully and the window appears. cargo clippy and cargo fmt --check pass cleanly.

Summary by CodeRabbit

  • Chores
    • Moved macOS-specific dependency entries into a platform-only configuration to tidy build settings.
    • Adjusted logging setup to include a macOS-only log target while keeping cross-platform outputs.
    • Result: clearer macOS build behavior and improved macOS diagnostics without affecting other platforms.

On Linux/Windows, tauri_plugin_log's Webview target deadlocks on the
first log::info! call inside setup(). The WebKitGTK IPC socket is
registered with mio (token=Token(1), interests=READABLE) before the
webview process exists, so the epoll event never fires and setup()
blocks forever - the app window never appears.

Fix by restricting the Webview log target to macOS only via
#[cfg(target_os = "macos")], where initialisation order is safe.
Stdout and LogDir targets are unaffected on all platforms.

Also fix Cargo.toml: macos-private-api cannot be in the base
[dependencies] on Linux because tauri-build validates that the feature
matches "macOSPrivateApi": true in the merged tauri.conf.json. That
key only exists in tauri.macos.conf.json, which is merged at build time
on macOS only. Move macos-private-api to
[target.'cfg(target_os = "macos")'.dependencies] so Cargo merges the
feature on macOS while Linux builds omit it cleanly.
Copilot AI review requested due to automatic review settings March 10, 2026 11:06
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 10, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 21e94b30-9763-436c-b6ea-2cd48934c61a

📥 Commits

Reviewing files that changed from the base of the PR and between ef58d0c and 45285d5.

📒 Files selected for processing (1)
  • src-tauri/src/lib.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src-tauri/src/lib.rs

📝 Walkthrough

Walkthrough

Reorganizes tauri dependency: moves macos-private-api feature into a macOS-specific target dependency in src-tauri/Cargo.toml. Refactors logging setup in src-tauri/src/lib.rs to build a targets vector conditionally including a Webview target on non-Linux macOS/Linux builds.

Changes

Cohort / File(s) Summary
Tauri dependency config
src-tauri/Cargo.toml
Moves macos-private-api feature out of the base [dependencies] and into a cfg(target_os = "macos") target-specific tauri entry.
Logging plugin configuration
src-tauri/src/lib.rs
Replaces inline tauri_plugin_log::Builder targets array with a closure that constructs a targets vector and conditionally adds a Webview target (excluded on Linux), then builds the Builder from that vector.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

I nibble bytes beneath the moonlight's glow,
Moving features where they ought to go,
Logs assemble, platforms sing along,
Tiny refactors—swift and strong! 🐇✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: fixing a Linux startup hang caused by the Webview log target deadlock.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes a Linux-only startup hang in the Tauri app by avoiding an early Webview log target path that can deadlock during setup(), and adjusts Cargo feature configuration so tauri-build validation passes on non-macOS platforms.

Changes:

  • Conditionally include tauri_plugin_log::TargetKind::Webview only for macOS.
  • Move tauri’s macos-private-api feature into a macOS-only dependency section, keeping protocol-asset in the base dependency.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src-tauri/src/lib.rs Makes the log plugin targets platform-conditional to avoid Linux startup deadlock.
src-tauri/Cargo.toml Splits tauri features by platform to satisfy tauri-build feature/allowlist validation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@MareDevi MareDevi mentioned this pull request Mar 10, 2026
@dannysmith
Copy link
Copy Markdown
Owner

@MareDevi Thanks for this. Gimme a few days to review and merge.

@dannysmith dannysmith merged commit a1380de into dannysmith:main Mar 12, 2026
4 checks passed
@dannysmith
Copy link
Copy Markdown
Owner

@MareDevi Just realised this is like a 15-line diff 😅 Looks good - thanks 🙂

dannysmith added a commit to dannysmith/tauri-template that referenced this pull request Mar 27, 2026
On Linux with WebKitGTK, the Webview log target causes app.emit() to
deadlock during setup() because the webview process doesn't exist yet.
The IPC socket registers with epoll but never receives a response,
blocking forever on the first log::info!() call.

Guard the Webview target with #[cfg(not(target_os = "linux"))]. Stdout
and LogDir targets continue to work on all platforms.

Ref: dannysmith/astro-editor#150

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
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.

3 participants