Skip to content

fix(events): background interactive hooks to prevent tmux freeze#53

Merged
rtalexk merged 1 commit into
mainfrom
fix/background-hooks
May 29, 2026
Merged

fix(events): background interactive hooks to prevent tmux freeze#53
rtalexk merged 1 commit into
mainfrom
fix/background-hooks

Conversation

@rtalexk

@rtalexk rtalexk commented May 29, 2026

Copy link
Copy Markdown
Owner

Context

Interactive hooks fire on user interactions (mouse scroll, window/session switch).
Currently, these hooks use synchronous run-shell commands, which block the tmux
server's command queue while demux event performs database work. When DB
operations stall on the SQLite lock (held by state-writer hooks), the tmux
server freezes mid-redraw, tearing the visual paint and breaking copy-mode
selection rendering.

This fix backgrounds the interactive hooks to allow tmux rendering to continue
while event handlers run concurrently, preventing the visual freeze.

What does this PR do

  • Adds -b flag to pane_focus, window_focus, and session_changed hooks to
    background their execution, preventing the tmux server from blocking on DB work.
  • Wraps pane_focus event handler logic in withEventLock to serialize
    concurrent invocations (since the hooks are now backgrounded) and prevent race
    conditions in sidebar repositioning.
  • Adds TestInteractiveHooksAreBackgrounded to verify that all four interactive
    hooks (after-select-pane, client-focus-in, after-select-window,
    client-session-changed) have the -b flag set.
  • Adds debug logging for pane_focus resolution and event processing.

Out of scope

None. All changes are contained to the event hook system.

Manual QA

Verify that interactive events (pane focus, window/session switch) no longer
freeze the tmux server's redraw cycle.

Prerequisites

1. demux is built and in PATH
demux --version

Expected: output shows version (e.g., demux dev).

2. Hooks are registered in the test tmux server
# Create a test session
tmux new-session -d -s test-demux -c ~

# Verify hooks are set
tmux show-hooks -t test-demux

Expected: output includes after-select-pane, after-select-window,
client-focus-in with -b flag in their run-shell commands.

Setup

  1. Build and install the binary:
    go build -o demux ./cmd/demux
    sudo mv demux /usr/local/bin/
  2. Create a fresh test session:
    tmux new-session -d -s test-render -c ~ -x 120 -y 40
    demux attach test-render
  3. Capture baseline: open several panes and note that window/pane switches render smoothly.

Scenario 1 — Rapid pane switches don't freeze render

Rapidly switch between panes in a multi-pane window
  1. In the test session, split into 3+ panes:
    tmux split-window -t test-render -h
    tmux split-window -t test-render -v
  2. Rapidly switch focus between panes (hold Alt+arrow or use mouse click):
    • Click pane 1 → pane 2 → pane 3 repeatedly for ~10 switches.
  3. Expected: No visual glitch, no torn paint, no delay in redraw. The cursor
    follows focus cleanly.
  4. Check debug logs (if enabled):
    tail -f ~/.cache/demux/demux.log | grep "pane_focus"
    Expected: log lines appear with no errors.

Scenario 2 — Rapid window switches don't freeze render

Create multiple windows and switch between them rapidly
  1. Create additional windows:
    tmux new-window -t test-render
    tmux new-window -t test-render
  2. Switch windows rapidly (Ctrl+N, Ctrl+P, or mouse click on window list):
    • Switch between windows 10+ times over 5 seconds.
  3. Expected: No visual freeze, smooth render, sidebar (if visible) repositions
    without lag or paint tears.
  4. Verify event processing in logs:
    tail -f ~/.cache/demux/demux.log | grep "window_focus"
    Expected: events logged with no errors.

Scenario 3 — Test suite passes

Run the test for hook backgrounding
cd /Users/rtalex/com.github/demux/main
go test ./internal/tmuxhooks -run TestInteractiveHooksAreBackgrounded -v

Expected: test passes, confirming all four interactive hooks have -b set.

Run all tmux hook tests:

go test ./internal/tmuxhooks -v

Expected: all tests pass.

Interactive hooks (pane_focus, window_focus, session_changed) fire on client
interactions (mouse scroll, window/session switch). A synchronous run-shell
blocks the tmux server's command queue while `demux event` does DB work, which
can stall on the SQLite lock, freezing the on-screen paint mid-redraw.

Backgrounding these hooks (-b flag) allows tmux rendering to continue while
the event handler runs concurrently. Serialize via withEventLock to prevent
concurrent sidebar mutations.

- Add -b flag to paneFocus, windowFocus, sessionChanged hooks
- Wrap pane_focus DB operations in withEventLock for serialization
- Add TestInteractiveHooksAreBackgrounded to guard hook backgrounding
@rtalexk rtalexk marked this pull request as ready for review May 29, 2026 20:08
@rtalexk rtalexk merged commit 20de040 into main May 29, 2026
4 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