Skip to content

Commit

Permalink
Merge pull request #5738 from bk2204/log-scanner-stderr
Browse files Browse the repository at this point in the history
Avoid deadlocking on log scanning with lots of output on stderr
  • Loading branch information
bk2204 committed May 7, 2024
2 parents 7ca57af + 9fd0060 commit 41612f7
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 2 deletions.
10 changes: 9 additions & 1 deletion git/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,10 @@ func gitNoLFSBuffered(args ...string) (*subprocess.BufferedCmd, error) {
return subprocess.BufferedExec("git", gitConfigNoLFS(args...)...)
}

func gitNoLFSBufferedStdout(args ...string) (*subprocess.BufferedCmd, error) {
return subprocess.StdoutBufferedExec("git", gitConfigNoLFS(args...)...)
}

// Invoke Git with enabled LFS filters
func git(args ...string) (*subprocess.Cmd, error) {
return subprocess.ExecCommand("git", args...)
Expand All @@ -225,6 +229,10 @@ func gitBuffered(args ...string) (*subprocess.BufferedCmd, error) {
return subprocess.BufferedExec("git", args...)
}

func gitBufferedStdout(args ...string) (*subprocess.BufferedCmd, error) {
return subprocess.StdoutBufferedExec("git", args...)
}

func CatFile() (*subprocess.BufferedCmd, error) {
return gitNoLFSBuffered("cat-file", "--batch-check")
}
Expand All @@ -247,7 +255,7 @@ func DiffIndex(ref string, cached bool, refresh bool, workingDir string) (*bufio
args = append([]string{"-C", workingDir}, args...)
}

cmd, err := gitBuffered(args...)
cmd, err := gitBufferedStdout(args...)
if err != nil {
return nil, err
}
Expand Down
10 changes: 9 additions & 1 deletion lfs/gitscanner_log.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,14 @@ func scanStashed(cb GitScannerFoundPointer) error {
func parseScannerLogOutput(cb GitScannerFoundPointer, direction LogDiffDirection, cmd *subprocess.BufferedCmd, filter *filepathfilter.Filter) {
ch := make(chan gitscannerResult, chanBufSize)

cherr := make(chan []byte)

go func() {
stderr, _ := io.ReadAll(cmd.Stderr)
cherr <- stderr
close(cherr)
}()

go func() {
scanner := newLogScanner(direction, cmd.Stdout)
scanner.Filter = filter
Expand All @@ -149,7 +157,7 @@ func parseScannerLogOutput(cb GitScannerFoundPointer, direction LogDiffDirection
io.ReadAll(cmd.Stdout)
ch <- gitscannerResult{Err: errors.New(tr.Tr.Get("error while scanning `git log`: %v", err))}
}
stderr, _ := io.ReadAll(cmd.Stderr)
stderr := <-cherr
err := cmd.Wait()
if err != nil {
ch <- gitscannerResult{Err: errors.New(tr.Tr.Get("error in `git log`: %v %v", err, string(stderr)))}
Expand Down
30 changes: 30 additions & 0 deletions subprocess/subprocess.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,36 @@ func BufferedExec(name string, args ...string) (*BufferedCmd, error) {
}, nil
}

// StdoutBufferedExec starts up a command and creates a stdin pipe and a
// buffered stdout pipe, with stderr directed to /dev/null, wrapped in a
// BufferedCmd. The stdout buffer will be of stdoutBufSize bytes.
func StdoutBufferedExec(name string, args ...string) (*BufferedCmd, error) {
cmd, err := ExecCommand(name, args...)
if err != nil {
return nil, err
}
stdout, err := cmd.StdoutPipe()
if err != nil {
return nil, err
}

stdin, err := cmd.StdinPipe()
if err != nil {
return nil, err
}

if err := cmd.Start(); err != nil {
return nil, err
}

return &BufferedCmd{
cmd,
stdin,
bufio.NewReaderSize(stdout, stdoutBufSize),
nil,
}, nil
}

// SimpleExec is a small wrapper around os/exec.Command.
func SimpleExec(name string, args ...string) (string, error) {
cmd, err := ExecCommand(name, args...)
Expand Down

0 comments on commit 41612f7

Please sign in to comment.