Skip to content

CLI: fix stalls and dropped logs after the ratatui 0.30 upgrade - #6003

Merged
nicoburns merged 1 commit into
DioxusLabs:mainfrom
nicoburns:fix-tui-log-cursor-query
Oct 24, 2026
Merged

nicoburns merged 1 commit into
DioxusLabs:mainfrom
nicoburns:fix-tui-log-cursor-query

Conversation

@nicoburns

Copy link
Copy Markdown
Member

Summary

Since #5954 (ratatui 0.29 → 0.30), the dx serve TUI stalls for ~2s on every log line and then silently drops it. Symptoms: the dashboard looks hung in odd places ("Installing tooling" / "Compiling n/m" for 30s+ with nothing printed), and t/v only seem to work sometimes - especially not during a build with --trace on.

Cause: in ratatui 0.30, Terminal::clear() queries the cursor position (ESC[6n), and insert_before - which render_log called once per log line - ends with clear(). The cursor query needs crossterm's input-reader lock, which the EventStream background thread holds while it is parked waiting for a key. So the query waits out its 2s timeout, errors, and the log line is lost. The lock is only free right after a keypress, hence the intermittent feel: a t pressed mid-build lands only once the queued cargo output has been "rendered" (2s per line), and with --trace that queue is ~1000 lines.

Fix:

  • Enable ratatui's scrolling-regions feature. Its insert_before sets a VT scroll region covering the rows above the viewport, scrolls that region, and draws the lines into the gap - it never clears the frame or queries the cursor (and the frame no longer flickers/redraws per log).
  • That makes the manual cursor/padding hack in render_log and serve/ansi_buffer.rs unnecessary: logs are built as styled Lines, word-wrapped with Paragraph, and inserted with a single insert_before per render. This is the "future" the old FIXME comments in render_log described.
  • TraceController::try_recv + a drain in the serve loop so an already-queued burst of trace messages is rendered in one pass instead of one redraw per line, keeping keyboard input responsive.
  • Drop the now-unused unicode-segmentation dependency.

Net: +54 / -232.

Test plan

Tested on macOS with a release build of dioxus-components (dx serve --release -p preview --features native --macos), which previously reproduced this reliably:

  • --trace from the start: ~1000 cargo lines render within the same second (before: 2s each / dropped).
  • r then t ×2 mid-build: each toggle handled the instant it was pressed (before: ~15s late).
  • v, / (viewport resize) work mid-build; frame intact; logs present in scrollback; app launches.
  • cargo clippy -p dioxus-cli --all-targets clean; cargo test -p dioxus-cli --bin dx 162/162.

Note: scroll-region insert_before relies on the terminal pushing lines scrolled off a top-anchored region into scrollback. That is standard (iTerm2, Terminal.app, tmux, kitty, Alacritty, WezTerm, VTE, Windows Terminal) but reviewers on other terminals may want to sanity-check dx serve --trace scrollback.

Since DioxusLabs#5954 (ratatui 0.29 -> 0.30), `Terminal::clear()` queries the cursor
position, and `insert_before` - which the serve TUI called once per log
line - ends with `clear()`. That query needs crossterm's input-reader lock,
which our `EventStream` background thread holds whenever it is waiting
for a key. So every log line blocked the serve loop for the 2s query
timeout, errored, and was silently dropped. The lock is only free right
after a keypress, which made `t`/`v` seem to work intermittently and let
status updates (e.g. "Installing tooling", "Compiling n/m") stall for
tens of seconds behind the log queue.

Switch to ratatui's `scrolling-regions` implementation of `insert_before`.
It scrolls a region above the viewport and draws the lines into the gap,
so it never clears the frame or queries the cursor. That also lets
`render_log` drop its manual cursor/padding hack and `ansi_buffer.rs`:
logs are now built as styled `Line`s, word-wrapped with `Paragraph`, and
inserted in one `insert_before` per render.

Also drain the already-queued burst of trace messages in the serve loop
before rendering, so cargo's ~1000 `Fresh ...` lines cost one scroll
instead of one redraw each and keyboard input is not starved.
@nicoburns nicoburns changed the title cli: fix 2s stall and dropped TUI logs after the ratatui 0.30 upgrade CLI: fix stalls and dropped logs after the ratatui 0.30 upgrade Oct 24, 2026
@nicoburns
nicoburns merged commit 48645cb into DioxusLabs:main Oct 24, 2026
23 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.

1 participant