Created subprocess.Cmd wrapper to autoclose any created pipes
Removing original fix for #1860
This commit is contained in:
Taylor Jones 2017-01-17 18:41:38 -05:00 committed by Taylor Jones
parent dd19c1b9c2
commit be73bc08dd
5 changed files with 54 additions and 11 deletions

@ -445,10 +445,7 @@ func RecentBranches(since time.Time, includeRemoteBranches bool, onlyRemote stri
return nil, fmt.Errorf("Failed to call git for-each-ref: %v", err)
}
cmd.Start()
defer func() {
outp.Close()
cmd.Wait()
}()
defer cmd.Wait()
scanner := bufio.NewScanner(outp)

46
subprocess/cmd.go Normal file

@ -0,0 +1,46 @@
package subprocess
import (
"io"
"os/exec"
)
// Thin wrapper around exec.Cmd. Takes care of pipe shutdown by
// keeping an internal reference to any created pipes. Whenever
// Cmd.Wait() is called, all created pipes are closed.
type Cmd struct {
*exec.Cmd
pipes []io.Closer
}
func (c *Cmd) StdoutPipe() (io.ReadCloser, error) {
stdout, err := c.Cmd.StdoutPipe()
c.pipes = append(c.pipes, stdout)
return stdout, err
}
func (c *Cmd) StderrPipe() (io.ReadCloser, error) {
stderr, err := c.Cmd.StderrPipe()
c.pipes = append(c.pipes, stderr)
return stderr, err
}
func (c *Cmd) StdinPipe() (io.WriteCloser, error) {
stdin, err := c.Cmd.StdinPipe()
c.pipes = append(c.pipes, stdin)
return stdin, err
}
func (c *Cmd) Wait() error {
for _, pipe := range c.pipes {
pipe.Close()
}
return c.Cmd.Wait()
}
func newCmd(cmd *exec.Cmd) *Cmd {
wrapped := &Cmd{Cmd: cmd}
return wrapped
}

@ -7,8 +7,8 @@ import (
)
// ExecCommand is a small platform specific wrapper around os/exec.Command
func ExecCommand(name string, arg ...string) *exec.Cmd {
func ExecCommand(name string, arg ...string) *Cmd {
cmd := exec.Command(name, arg...)
cmd.Env = env
return cmd
return newCmd(cmd)
}

@ -8,9 +8,9 @@ import (
)
// ExecCommand is a small platform specific wrapper around os/exec.Command
func ExecCommand(name string, arg ...string) *exec.Cmd {
func ExecCommand(name string, arg ...string) *Cmd {
cmd := exec.Command(name, arg...)
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
cmd.Env = env
return cmd
return newCmd(cmd)
}

@ -6,7 +6,6 @@ import (
"encoding/json"
"fmt"
"io"
"os/exec"
"path/filepath"
"regexp"
"strings"
@ -52,7 +51,7 @@ func (t *traceWriter) Flush() {
type customAdapterWorkerContext struct {
workerNum int
cmd *exec.Cmd
cmd *subprocess.Cmd
stdout io.ReadCloser
bufferedOut *bufio.Reader
stdin io.WriteCloser
@ -70,7 +69,8 @@ func NewCustomAdapterInitRequest(op string, concurrent bool, concurrentTransfers
return &customAdapterInitRequest{"init", op, concurrent, concurrentTransfers}
}
type customAdapterTransferRequest struct { // common between upload/download
type customAdapterTransferRequest struct {
// common between upload/download
Event string `json:"event"`
Oid string `json:"oid"`
Size int64 `json:"size"`