Skip to content

Fast typing drops intermediate frames — characters not rendered while cursor advances #224

@tarikguney

Description

@tarikguney

Description

When typing quickly in a psmux pane, the cursor advances correctly but characters are not rendered on screen. Typing slowly works fine — each character appears as expected. This is a regression that did not exist before.

Steps to Reproduce

  1. Open a psmux session
  2. Type quickly in any shell (bash, pwsh, etc.)
  3. Observe that the cursor moves forward with each keystroke, but some or all characters behind the cursor fail to render
  4. Typing slowly renders every character correctly

Root Cause

Commit 694156e ("fix: bounded frame push prevents copy-mode scroll memory leak") replaced the unbounded mpsc::channel per client with a single-slot Arc<Mutex<Option<String>>>. The push_frame() function now overwrites any unconsumed frame in the slot:

// src/types.rs — push_frame()
slots.retain(|(_, slot)| {
    // overwrites any pending frame — only "latest" is kept
    *pending = Some(frame.to_string());
    ...
});

And the writer thread in connection.rs polls the slot on a 5ms timeout:

// 2. Check the frame slot — take the latest pushed frame
let frame = frame_lock.lock().ok().and_then(|mut slot| slot.take());

During fast typing:

  1. Each keystroke triggers a PTY update → server generates a new frame
  2. If multiple frames arrive within the 5ms polling window, intermediate frames are overwritten and never delivered to the client
  3. The client only receives the "latest" frame, which may have the correct cursor position but intermediate rendering states are lost
  4. The client-side skip logic (dump_buf == prev_dump_buf) can further compound this if timing causes a stale comparison

The previous unbounded channel design queued all frames, guaranteeing each one was delivered and rendered. The single-slot design trades that guarantee for bounded memory — fixing the copy-mode scroll leak but breaking fast typing.

Expected Behavior

All typed characters should render on screen regardless of typing speed.

Suggested Fix

Consider a bounded channel (e.g., mpsc::sync_channel with a small capacity like 8-16) instead of a single-slot overwrite. This would:

  • Still bound memory (unlike the original unbounded channel)
  • Allow a small burst of frames to queue without being dropped
  • Only drop frames under sustained high-throughput scenarios (like the scroll case the fix was targeting)

Alternatively, the frame slot could use a dirty flag + condvar to wake the writer thread immediately on each new frame rather than relying on the 5ms poll interval, reducing the window for overwrites.

Environment

  • Windows 11
  • psmux latest (post-694156e)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions