Skip to content

fix: avoid event-loop stalls from synchronous tmux/ps calls#100

Merged
Ark0N merged 1 commit into
Ark0N:masterfrom
TeigenZhang:fix/event-loop-stalls
Jun 1, 2026
Merged

fix: avoid event-loop stalls from synchronous tmux/ps calls#100
Ark0N merged 1 commit into
Ark0N:masterfrom
TeigenZhang:fix/event-loop-stalls

Conversation

@TeigenZhang
Copy link
Copy Markdown
Contributor

Summary

The session manager called execSync for tmux mouse-mode and list-panes queries on the main thread. Under load (many sessions / agent panes) these synchronous spawns block Node's event loop, stalling SSE broadcasts and PTY I/O.

This converts those calls to async (execAsync) and adds a lightweight event-loop-monitor utility that samples loop-delay and logs when a stall threshold is exceeded, making future regressions observable.

Changes

  • tmux-manager.ts: enableMouseMode/disableMouseMode/listPanes now use execAsync instead of execSync
  • utils/event-loop-monitor.ts (new): periodic event-loop delay sampler
  • utils/index.ts: export the monitor
  • server.ts: start the monitor on boot

Test plan

  • tsc --noEmit passes
  • Observe no main-thread stalls under multi-session load

The stats collector (~2s) and mouse-mode sync (5s) ran execSync (pgrep/ps/
list-panes, 5s timeout each) per session on the server's single thread,
blocking the event loop. With several sessions or a momentarily slow tmux this
froze port 3000 for seconds-to-tens-of-seconds while the process stayed alive
and other ports were unaffected — self-healing, so it never restarted and the
60s loopback healthcheck missed it. Convert these hot-path calls to execAsync.

Also add an always-on event-loop lag monitor (utils/event-loop-monitor.ts) that
logs stalls >=1s to the web log, so this otherwise-invisible class of incident
leaves a quantified, timestamped trace.
@Ark0N
Copy link
Copy Markdown
Owner

Ark0N commented Jun 1, 2026

Thank you as always for contributing, @TeigenZhang! 🙏

Reviewed and verified locally on the PR branch:

  • tsc --noEmit clean
  • npm run lint clean
  • npm run format:check clean
  • npm run build (esbuild) succeeds
  • ✅ All internal callers of listPanes/enableMouseMode/disableMouseMode/syncMouseMode updated to await; no external callers left unhandled

Great catch on the blocking execSync calls stalling the event loop under multi-session load — and the event-loop-monitor is a nice touch for making future regressions observable. Merging now.

@Ark0N Ark0N merged commit 06f9ff6 into Ark0N:master Jun 1, 2026
1 check 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.

2 participants