[bug] iOS: debug-build stdout/stderr redirector deadlocks itself when OS_ACTIVITY_DT_MODE is set

Open
#16,482 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
66/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
ios, rust
Domain
backend, mobile

Research direction

Start by reading crates/tauri/mobile/ios-api/Sources/Tauri/Logger.swift, especially StdoutRedirector and its read handler; reproduce with an iOS debug simulator build launched with OS_ACTIVITY_DT_MODE set. The issue describes the recursive logging path and several possible fixes. Done when mirrored log output no longer feeds back into the redirector or blocks writes; the payload names no test file.

Written by the indexing model from the issue text.

Description

platform: iOS status: needs triage type: bug
Describe the bug

In iOS debug builds, the stdout/stderr redirector that mobile_entry_point installs (tauri::log_stdout()) can feed its own output back into itself and deadlock. It happens when the app is launched with OS_ACTIVITY_DT_MODE in its environment (any value; NO and 0 trigger it too).

What happens:

  1. StdoutRedirector (crates/tauri/mobile/ios-api/Sources/Tauri/Logger.swift) dup2s stdout and stderr into pipes, and its read handler re-logs each chunk through Logger.info → os_log.
  2. With OS_ACTIVITY_DT_MODE present, the OS mirrors every os_log line to stderr, which is now the redirector's own pipe.
  3. The only recursion guard is trimmed.hasPrefix("OSLOG-"). On the iOS 27.0 simulator the mirrored lines use a plain format (<timestamp> AppName[pid:tid] [app] ...), so the guard doesn't match and every line is logged again, nested one level deeper ([app] [stderr] [app] [stderr] ...).
  4. Within seconds the reader blocks in writev while writing to the pipe that only it drains (64 KB buffer), so it deadlocks itself. From then on, any thread that writes to stderr blocks forever.

The visible symptom for us was XCUITest: every UI query timed out at 0% CPU with Failed to get matching snapshots: Timed out while evaluating UI query., because XCTest's in-app automation threads write to stderr. The same may affect a debug build launched from anything that sets OS_ACTIVITY_DT_MODE.

Release builds aren't affected, because Logger.enabled is only always-on under #if DEBUG.

Reproduction

Observed in an app on tauri 2.12.4 / tauri-macros 2.7.4. The same redirector code is in 2.12.5 and on dev today. I haven't reduced it to a fresh template app yet, but the code path runs for every iOS app through mobile_entry_point.

  1. Build any Tauri 2 iOS app in debug for the simulator.
  2. Launch it with the variable set, for example:
    SIMCTL_CHILD_OS_ACTIVITY_DT_MODE=YES xcrun simctl launch booted <bundle id>
    or, in an XCUITest, app.launchEnvironment["OS_ACTIVITY_DT_MODE"] = "YES"; app.launch().
  3. Watch the device log: tens of thousands of self-nesting [stderr] lines appear in the first minute (about 85,000 in our run), then the process sits at 0% CPU.
  4. Any UI query from XCUITest now times out.

Without the variable, the same build logs 2 to 4 [stderr] lines and XCUITest reads the full accessibility tree in under a second.

Expected behavior

The redirector shouldn't re-ingest its own os_log output, whatever format the OS uses to mirror it to stderr, and it should never block on its own pipe.

Possible fixes, for whoever picks this up:

  • Write the re-logged text straight to the original stderr fd instead of through os_log when OS_ACTIVITY_DT_MODE is present.
  • Guard with a reentrancy flag around the Logger.info call, instead of matching a line prefix.
  • Skip chunks that already carry the redirector's own [stdout] / [stderr] marker.
Full tauri info output
macOS 27.0.1 (26A434), Xcode 27.0 (27A266a), rustc 1.99.0
iOS 27.0 simulator runtime (24A434)
tauri 2.12.4 (same code in 2.12.5 and on dev)
tauri-macros 2.7.4

(Trimmed to the relevant versions.)

Stack trace
Thread blocked (from `sample`, 0% CPU):
  StdoutRedirector.createReader(...) closure   Logger.swift:73
  Logger.info
  os_log
  _os_log_impl_mirror_to_stderr
  writev
Main thread: idle in the run loop.
Additional context

Workaround: keep OS_ACTIVITY_DT_MODE out of the test launch environment. Setting it to NO doesn't help, since presence alone triggers the loop.

Dominant language
Rust
Stars
113k
Forks
4.2k
Avg merge
2d 8h
Merged PRs (30d)
82

Getting set up

Open in Codespaces

Starts the project's dev container in your browser, under your own GitHub account.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from tauri-apps/tauri

All issues in tauri-apps/tauri

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.