Skip to content

Fix commands sometimes returning empty output when many run at once - #774

Merged
hannesa2 merged 1 commit into
masterfrom
fix-task-output-lost-under-load
Oct 24, 2026
Merged

hannesa2 merged 1 commit into
masterfrom
fix-task-output-lost-under-load

Conversation

@goneng

@goneng goneng commented Oct 24, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

When the machine is busy, for example when many GitX windows start at once,
GitX sometimes reads nothing from a git command that actually ran fine.
For git --version that makes GitX conclude that no usable git exists, which is the
"Invalid git path" alert from #744 or a repository that fails to open with "Could not find a git binary".
Any other command run through the same code can lose its output in the same way.

This PR makes GitX wait until a command's output has been fully read before it reports
the command as finished.

I reproduced it by opening about a dozen repositories at once with a build of #766.
The log showed Could not parse the output of '/opt/homebrew/bin/git --version':
with nothing after the colon, for /opt/homebrew/bin/git and /usr/bin/git alike, and
none of those runs had a non-zero exit.

Details

PBTask collects output in a read handler on the pipe, and learns that the process
exited through the NSTask termination handler.
The two run on different threads with no ordering between them.
When the process exits first, the success path in performTaskOnQueue:completionHandler: clears
the read handler and returns standardOutputData before the handler has read what is in the pipe,
so the task succeeds with empty data.
The non-zero-exit path has the same race, so the output attached to an error can also be empty.

  • outputDrained: a semaphore signalled by the read handler when it reads EOF,
    after it has appended all data.
  • The termination handler waits on it before looking at the exit status or the output,
    so both the success and the error path see complete output.
  • The wait is limited to 5 seconds and logs a line if it runs out.
    A child process that inherited the pipe, such as a background git daemon,
    can keep it open after git exits, and a command must not hang because of that.
    On timeout the behavior is what it was before this change.
  • PBTaskTests runs 400 /bin/echo tasks concurrently and expects the full output from each.
    Before the fix it failed with a large share of empty results and no error, and it passes now.

Related: #744, #766. #766 is still worth having (validation off the main thread, fallback if the configured path fails), but it cannot help while the search itself gets empty output from every candidate.

Test plan

  • make test: 348 tests, 0 failures, including the new PBTaskTests.
  • The new test fails on master with empty outputs and passes with this change.
  • Manual: with a build of this branch, open many repositories at once
    (for r in ~/GitRepos/*/; do open -n -a GitX.app --args -NSOpen "$r"; done)
    while watching log stream --process GitX --predicate 'eventMessage CONTAINS "git"'.
    There should be no Could not parse the output of lines with an empty output,
    and no "Invalid git path" alert.

Make GitX wait for a finished command's output to be fully read before
reporting the command as done. Until now, a busy machine could make a
successful command look like it printed nothing.

- Signal from the read handler once the pipe reaches EOF.
- Wait for that signal in the termination handler, for up to 5 seconds,
  before the output is used or attached to an error.
- Add a test that runs 400 short commands concurrently and checks that
  each returns its full output.
@goneng goneng added the bugfix label Oct 24, 2026
@goneng
goneng marked this pull request as ready for review October 24, 2026 17:55
@goneng
goneng requested a review from hannesa2 October 24, 2026 18:04
@hannesa2
hannesa2 merged commit f710173 into master Oct 24, 2026
9 of 12 checks passed
@hannesa2
hannesa2 deleted the fix-task-output-lost-under-load branch October 24, 2026 21:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants