docs(pane_interaction, workspace_setup): the same shell-echo race #706 fixed in automation_patterns

Open
#715 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
52/100
Issue type
Documentation
Clarity
Mostly clear
Activity status
Quiet
Tech stack
python, shell
Domain
cli, documentation

Research direction

Start with docs/topics/pane_interaction.md, focusing on run_and_capture and check_for_errors, then inspect docs/topics/workspace_setup.md and compare the fixes in #706 and #709. Check the related completion predicate in #654 for context. Done means the examples no longer treat echoed commands as output, and their checks wait for or match genuine command output.

Written by the indexing model from the issue text.

Description

#706 / #709 fix the echo race in {ref}automation-patterns. The identical pattern is still live on two other pages, and one of them is the page automation_patterns.md sends readers to first.

The fault is always the same: {meth}~libtmux.Pane.send_keys types the command into the pane, so the shell echoes it straight back into the buffer that capture_pane() reads. Any completion check that substring-scans the whole pane matches its own command line, and returns before the command has produced a single byte of output.

docs/topics/pane_interaction.md

run_and_capture (v0.61.0) is the worst instance, because it builds the marker into the command it sends:

pane.send_keys(f'{command}; echo {marker}')     # the echo now contains __DONE__
...
output_str = '\n'.join(output)
if marker in output_str:                        # ...so this matches immediately
    return output

It returns on the first poll, in milliseconds, with only the echoed command on screen. Its TimeoutError branch is unreachable. The doc's own assertion ('captured text' in '\n'.join(result)) then passes off the echo line rather than the command's output, so the example looks like it works.

check_for_errors on the same page is the same helper #709 just fixed in automation_patterns.md, duplicated:

output = '\n'.join(pane.capture_pane())
for pattern in error_patterns:
    if pattern in output:
        return True

A healthy mytool --log-level=ERROR is reported as a crash, because ERROR is in the command line the shell echoed.

docs/topics/workspace_setup.md

A bare sleep followed by a whole-pane substring scan:

time.sleep(0.2)
'Task A' in '\n'.join(pane_a.capture_pane())

Passes off the echo, not the output.

Suggested fix

Same as #709, and it should be stated once and reused rather than re-derived per page:

  • When the command is yours to change, synchronize with {meth}~libtmux.Server.wait_for instead of polling. tmux wait-for is race-free by construction: a signal with no waiter is remembered, so there is no lost wakeup.
  • When a poll is genuinely needed, match complete output lines that cannot also occur in the echoed input — not substrings of the joined pane.
  • Have the command tag the lines it owns, and let the shell assemble the tag so the literal never appears in what you typed (printf 'out%s%s\n' : ok, not printf 'out:%s\n' ok). This matters because a long command wraps: the wrapped continuation of the echo is its own line, so a tag that merely sits mid-line in what you sent can still end up starting one. #709 hit exactly this.

Related: #654 is the same root cause in the test suite (a completion predicate matching the marker inside the shell's command echo).

Dominant language
Python
Stars
1.2k
Forks
127
Avg merge
2h 13m
Merged PRs (30d)
1

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from tmux-python/libtmux

All issues in tmux-python/libtmux

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.