Skip to content

fix(core): avoid blocking event loop during TUI PTY resize#34385

Merged
FrozenPandaz merged 3 commits intomasterfrom
fix/tui-inline-to-full-hang
Feb 17, 2026
Merged

fix(core): avoid blocking event loop during TUI PTY resize#34385
FrozenPandaz merged 3 commits intomasterfrom
fix/tui-inline-to-full-hang

Conversation

@AgentEnder
Copy link
Copy Markdown
Member

When switching from inline mode to full-screen TUI (or during window resize), the PTY resize operation reparsed ALL raw terminal output through a new vt100 parser synchronously on the event loop. For tasks with large output, this caused a noticeable hang.

Add resize_async() which moves the expensive reparse to a background thread using a snapshot-and-replay pattern:

  1. Quick snapshot of raw output (brief read lock)
  2. Expensive reparse on background thread (no locks held)
  3. Quick swap with replay of any new output (brief write lock)

A generation counter prevents stale resizes from overwriting newer ones.

Also combine two separate O(n) scrollback processing calls in inline mode into a single pass.

@AgentEnder AgentEnder requested review from a team as code owners February 10, 2026 03:00
@netlify
Copy link
Copy Markdown

netlify Bot commented Feb 10, 2026

Deploy Preview for nx-dev ready!

Name Link
🔨 Latest commit 4d92aa8
🔍 Latest deploy log https://app.netlify.com/projects/nx-dev/deploys/698f779c8ba7a7000806fd34
😎 Deploy Preview https://deploy-preview-34385--nx-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link
Copy Markdown

netlify Bot commented Feb 10, 2026

Deploy Preview for nx-docs ready!

Name Link
🔨 Latest commit 4d92aa8
🔍 Latest deploy log https://app.netlify.com/projects/nx-docs/deploys/698f779c99704400089be7c2
😎 Deploy Preview https://deploy-preview-34385--nx-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@nx-cloud
Copy link
Copy Markdown
Contributor

nx-cloud Bot commented Feb 10, 2026

View your CI Pipeline Execution ↗ for commit 4d92aa8

Command Status Duration Result
nx affected --targets=lint,test,test-kt,build,e... ✅ Succeeded 53m 37s View ↗
nx run-many -t check-imports check-lock-files c... ✅ Succeeded 4m 23s View ↗
nx-cloud record -- nx-cloud conformance:check ✅ Succeeded 8s View ↗
nx-cloud record -- nx format:check ✅ Succeeded <1s View ↗
nx-cloud record -- nx sync:check ✅ Succeeded <1s View ↗

☁️ Nx Cloud last updated this comment at 2026-02-13 20:11:34 UTC

@AgentEnder AgentEnder force-pushed the fix/tui-inline-to-full-hang branch from 8b9d228 to 6fc62fe Compare February 10, 2026 05:23
Comment thread packages/nx/src/native/tui/pty.rs
@AgentEnder AgentEnder force-pushed the fix/tui-inline-to-full-hang branch 2 times, most recently from 65a2868 to f404353 Compare February 10, 2026 18:30
@github-actions
Copy link
Copy Markdown
Contributor

🐳 We have a release for that!

This PR has a release associated with it. You can try it out using this command:

npx create-nx-workspace@22.5.0-pr.34385.f404353 my-workspace

Or just copy this version and use it in your own command:

22.5.0-pr.34385.f404353
Release details 📑
Published version 22.5.0-pr.34385.f404353
Triggered by @AgentEnder
Branch fix/tui-inline-to-full-hang
Commit f404353
Workflow run 21877839125

To request a new release for this pull request, mention someone from the Nx team or the @nrwl/nx-pipelines-reviewers.

@AgentEnder AgentEnder force-pushed the fix/tui-inline-to-full-hang branch from f404353 to 5b7aba4 Compare February 12, 2026 14:38
Comment on lines +334 to +338
let mut state = state_arc.lock();
if generation_arc.load(Ordering::SeqCst) != generation_at_dispatch {
state.processing = false;
return;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Race condition: when a resize supersedes the background scrollback processing, pending_lines contains lines wrapped at stale column widths but are not cleared. These invalid lines will be returned to the renderer on the next frame.

Impact: Terminal output will be rendered with incorrect wrapping, causing visual corruption until enough new output arrives to flush the stale buffer.

Fix: Clear the stale pending lines when a resize is detected:

let mut state = state_arc.lock();
if generation_arc.load(Ordering::SeqCst) != generation_at_dispatch {
    state.pending_lines.clear();
    state.bg_scrollback_cursor = 0;
    state.processing = false;
    return;
}
Suggested change
let mut state = state_arc.lock();
if generation_arc.load(Ordering::SeqCst) != generation_at_dispatch {
state.processing = false;
return;
}
let mut state = state_arc.lock();
if generation_arc.load(Ordering::SeqCst) != generation_at_dispatch {
state.pending_lines.clear();
state.bg_scrollback_cursor = 0;
state.processing = false;
return;
}

Spotted by Graphite Agent

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

@AgentEnder AgentEnder force-pushed the fix/tui-inline-to-full-hang branch 4 times, most recently from 01eef4e to 124fc68 Compare February 12, 2026 16:00
@github-actions
Copy link
Copy Markdown
Contributor

Failed to publish a PR release of this pull request, triggered by @AgentEnder.
See the failed workflow run at: https://github.com/nrwl/nx/actions/runs/21954442042

Copy link
Copy Markdown
Contributor

@nx-cloud nx-cloud Bot left a comment

Choose a reason for hiding this comment

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

Important

At least one additional CI pipeline execution has run since the conclusion below was written and it may no longer be applicable.

Nx Cloud has identified a possible root cause for your failed CI:

We classified this failure as environment_state rather than code_change. The error occurs in Vitest's worker pool IPC layer (write EPIPE) with MaxListenersExceededWarning, not in the modified TUI resize code paths. The 10.4% flakiness rate and npm-vs-pnpm inconsistency indicate test infrastructure cleanup issues rather than deterministic breakage from the async PTY changes.

No code changes were suggested for this issue.

🔂 A CI rerun has been triggered by adding an empty commit to this branch.

Nx Cloud View detailed reasoning on Nx Cloud ↗


🎓 Learn more about Self-Healing CI on nx.dev

@github-actions
Copy link
Copy Markdown
Contributor

Failed to publish a PR release of this pull request, triggered by @AgentEnder.
See the failed workflow run at: https://github.com/nrwl/nx/actions/runs/21954442042

@AgentEnder AgentEnder force-pushed the fix/tui-inline-to-full-hang branch from 9c44ded to 1e82495 Compare February 12, 2026 19:47
When switching from inline mode to full-screen TUI (or during window
resize), the PTY resize operation reparsed ALL raw terminal output
through a new vt100 parser synchronously on the event loop. For tasks
with large output, this caused a noticeable hang.

Add `resize_async()` which moves the expensive reparse to a background
thread using a snapshot-and-replay pattern:
1. Quick snapshot of raw output (brief read lock)
2. Expensive reparse on background thread (no locks held)
3. Quick swap with replay of any new output (brief write lock)

A generation counter prevents stale resizes from overwriting newer ones.

Also combine two separate O(n) scrollback processing calls in inline
mode into a single pass.
@AgentEnder AgentEnder force-pushed the fix/tui-inline-to-full-hang branch from 3949192 to 4d92aa8 Compare February 13, 2026 19:12
@FrozenPandaz FrozenPandaz merged commit 130cec4 into master Feb 17, 2026
24 checks passed
@FrozenPandaz FrozenPandaz deleted the fix/tui-inline-to-full-hang branch February 17, 2026 23:07
FrozenPandaz pushed a commit that referenced this pull request Feb 20, 2026
When switching from inline mode to full-screen TUI (or during window
resize), the PTY resize operation reparsed ALL raw terminal output
through a new vt100 parser synchronously on the event loop. For tasks
with large output, this caused a noticeable hang.

Add `resize_async()` which moves the expensive reparse to a background
thread using a snapshot-and-replay pattern:
1. Quick snapshot of raw output (brief read lock)
2. Expensive reparse on background thread (no locks held)
3. Quick swap with replay of any new output (brief write lock)

A generation counter prevents stale resizes from overwriting newer ones.

Also combine two separate O(n) scrollback processing calls in inline
mode into a single pass.

(cherry picked from commit 130cec4)
@github-actions
Copy link
Copy Markdown
Contributor

This pull request has already been merged/closed. If you experience issues related to these changes, please open a new issue referencing this pull request.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Feb 23, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants