Repository navigation
Fix commands sometimes returning empty output when many run at once - #774
Merged
Merged
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 --versionthat 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/gitand/usr/bin/gitalike, andnone of those runs had a non-zero exit.
Details
PBTaskcollects output in a read handler on the pipe, and learns that the processexited through the
NSTasktermination handler.The two run on different threads with no ordering between them.
When the process exits first, the success path in
performTaskOnQueue:completionHandler:clearsthe read handler and returns
standardOutputDatabefore 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.
so both the success and the error path see complete output.
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.
PBTaskTestsruns 400/bin/echotasks 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 newPBTaskTests.(
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 oflines with an empty output,and no "Invalid git path" alert.