aboutsummaryrefslogtreecommitdiffstats
path: root/zellij-server/src/pty_writer.rs (follow)
Commit message (Collapse)AuthorAge
* fix: handle short writes in write_to_tty_stdin to prevent paste truncation ↵Edgars Nemše2026-03-12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | (#4818) * fix: handle short writes in write_to_tty_stdin to prevent paste truncation On macOS the kernel PTY buffer is only 4-16 KiB, so a single write() call for a large paste returns a short write count rather than blocking until all bytes are accepted. The current code returns this partial count without retrying, silently dropping the remaining bytes. This wraps the write in a retry loop that handles: - Short writes (advances the buffer offset and retries) - EINTR (retries immediately) - EAGAIN (sleeps 1ms then retries) Without this fix, pasting ~1 KiB+ of text into a terminal pane loses everything beyond the first kernel-buffer-full. Includes a test that exercises the fix using a real PTY pair with O_NONBLOCK set on the master fd to force short writes. * fix: cap EAGAIN retries at 50 to prevent infinite busy-wait Per reviewer feedback, add a retry counter that caps consecutive EAGAIN retries at 50 and logs an error if the limit is reached. The counter resets on any successful write progress, so it only triggers when the PTY is genuinely stuck. * fix: use poll(POLLOUT) instead of sleep-retry loop for EAGAIN handling Replace the 50-retry sleep(1ms) busy-wait with poll(POLLOUT, 5s timeout). This properly waits for fd writability without CPU spinning and returns an error on timeout instead of silently returning Ok(partial) — which the caller (pty_writer_main) would ignore, causing silent data loss. Tests: - write_to_tty_stdin_delivers_all_bytes: remove flaky reader delay, use concurrent reader, move master close after reader join to avoid macOS kernel buffer flush race - write_all_to_fd_errors_on_stuck_pty: new test verifying timeout returns Err on stuck PTY (uses 100ms timeout for speed) * fix: re-queue partial PTY writes instead of blocking PtyWriter thread Replace the poll(POLLOUT) blocking loop with a non-blocking re-queue approach as suggested in review. On partial write or EAGAIN: - write_to_tty_stdin now drains as much as the kernel accepts in one pass and returns the count (may be 0 on EAGAIN) - PtyWriter re-queues unwritten bytes back onto its own channel, letting other terminals' writes proceed between retries - Retry count tracks consecutive zero-progress attempts (reset on any forward progress), drops bytes after 50 retries with log::error - yield_now() before re-queue on zero progress to avoid tight spin - Guard against write() returning Ok(0) on non-empty buffer - Wire up PtyWriter's self-sender (was None, now Some(&to_pty_writer)) * fix: per-terminal write buffering to handle short writes and EAGAIN Replace re-queue approach with per-terminal pending write buffers (HashMap<u32, VecDeque<PendingWrite>>). Uses recv_timeout(10ms) when pending data exists, blocking recv when idle. 10MB per-terminal cap drops buffer on overflow. Terminal errors clear the queue. Adds Bus::recv_timeout via crossbeam Select::select_timeout. Removes tcdrain from write path. * use safe accessor methods and saturating substitutions * add tests for ptywriter * rustfmt * fix tests by not assuming kernel buffer sizes * rustfmt * add pr --------- Co-authored-by: Aram Drevekenin <aram@poor.dev>
* Allow writing characters, bytes and keys to specific panes from the CLI (#4691)Aram Drevekenin2026-02-10
| | | | | | | | | | | | | * initial implementation * fix tests * implement zellij action send-keys * rustfmt * add test * fix tests and add pr
* fix(rendering): occasional glitches while resizing (#2621)Aram Drevekenin2023-07-12
|
* refactor(plugins): change the data flow (#1934)Aram Drevekenin2022-11-15
| | | | | | | | | * refactor(plugins): do not block render loop * refactor(plugins): cleanup * style(fmt): rustfmt * fix(plugins): various rendering pipeline fixes
* errors: Don't unwrap in `server::pty_writer` (#1872)har7an2022-10-28
| | | | | | | | * server/pty_writer: Don't unwrap and handle occuring errors instead. Replace calls to `log::error` with `non_fatal` instead. * server/pty_writer: Apply rustfmt
* feat(ux): rerun command pane (#1787)Aram Drevekenin2022-10-11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * chore(config): default kdl keybindings config * tests * work * refactor(config): move stuff around * work * tab merge layout * work * work * layouts working * work * layout tests * work * work * feat(parsing): kdl layouts without config * refactor(kdl): move stuff around * work * tests(layout): add cases and fix bugs * work * fix(kdl): various bugs * chore(layouts): move all layouts to kdl * feat(kdl): shared keybidns * fix(layout): do not count fixed panes toward percentile * fix(keybinds): missing keybinds and actions * fix(config): adjust default tips * refactor(config): move stuff around * fix(tests): make e2e tests pass * fix(kdl): add verbose parsing errors * fix(kdl): focused tab * fix(layout): corret default_tab_template behavior * style(code): fix compile warnings * feat(cli): send actions through the cli * fix(cli): exit only when action is done * fix(cli): open embedded pane from floating pane * fix(cli): send actions to other sessions * feat(cli): command alias * feat(converter): convert old config * feat(converter): convert old layout and theme files * feat(kdl): pretty errors * feat(client): convert old YAML files on startup * fix: various bugs and styling issues * fix: e2e tests * fix(screen): propagate errors after merge * style(clippy): lower clippy level * fix(tests): own session_name variable * style(fmt): rustfmt * fix(cli): various action fixes * style(fmt): rustfmt * fix(themes): loading of theme files * style(fmt): rustfmt * fix(tests): theme fixtures * fix(layouts): better errors on unknown nodes * fix(kdl): clarify valid node terminator error * fix(e2e): adjust close tab test * fix(e2e): adjust close tab test again * style(code): cleanup some comments * get command panes not to exit on command exit * separate terminal pane_ids from raw_fds * render frame according to exit status * re-run command on enter and close pane on ctrl-c * proper error when command is not found * make ui nicer * initial pane title for command panes * fix pane override bug * reap terminal_ids from os_input_output on pane close * bool floating flag * some ui tweaks * fix tests * make rustfmt happy * e2e test for command pane * fix various concurrency issues * rename command to run in the cli * rustfmt * style(fmt): rustfmt * fix(e2e): command => run * fix(e2e): command => run in snapshot too!
* fix(terminal): SGR/UTF8 mouse reporting in terminal panes (#1664)Aram Drevekenin2022-08-17
| | | | | | | | | | | | | | | | | | | | | | | * work * work * fix: selection mishandling * style(fmt): rustfmt * style(comments): remove outdated * style(clippy): make clippy happy * fix(mouse): off by one sgr/utf8 reporting * style(fmt): rustfmt * fix(mouse): correctly report drag event code * fix(input): support mouse middle click * style(fmt): rustfmt
* add(style): add trailing comma in match blocks (#1483)a-kenji2022-06-10
| | | This makes it easier to distinguish from normal blocks
* fix: ensure pty_writer thread closes (#1422)Thomas Linford2022-05-17
|
* fix(pty): paste freeze with large amounts of text (#1383)Thomas Linford2022-05-16
add pty writer thread to avoid screen thread blocking on unistd::write