Skip to content

Commit

Permalink
Merge pull request #1335 from bosun-monitor/execTimeout
Browse files Browse the repository at this point in the history
util: reworking how util exec works with timeouts
  • Loading branch information
kylebrandt committed Sep 20, 2015
2 parents 4a03e8d + 3a01329 commit 4f5692d
Showing 1 changed file with 23 additions and 22 deletions.
45 changes: 23 additions & 22 deletions util/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io"
"os"
"os/exec"
"strings"
"time"

"bosun.org/slog"
Expand All @@ -33,30 +34,30 @@ func Command(timeout time.Duration, stdin io.Reader, name string, arg ...string)
slog.Infof("executing command: %v %v", name, arg)
}
c := exec.Command(name, arg...)
var b bytes.Buffer
c.Stdout = &b
b := &bytes.Buffer{}
c.Stdout = b
c.Stdin = stdin
done := make(chan error, 1)
go func() {
done <- c.Run()
}()
interrupt := time.After(timeout)
kill := time.After(timeout * 2)
for {
select {
case err := <-done:
return &b, err
case <-interrupt:
if c.Process != nil {
c.Process.Signal(os.Interrupt)
}
case <-kill:
if c.Process != nil {
c.Process.Kill()
}
return nil, ErrTimeout
}
if err := c.Start(); err != nil {
return nil, err
}
timedOut := false
intTimer := time.AfterFunc(timeout, func() {
slog.Errorf("Process taking too long. Interrupting: %s %s", name, strings.Join(arg, " "))
c.Process.Signal(os.Interrupt)
timedOut = true
})
killTimer := time.AfterFunc(timeout, func() {
slog.Errorf("Process taking too long. Killing: %s %s", name, strings.Join(arg, " "))
c.Process.Signal(os.Interrupt)
timedOut = true
})
err := c.Wait()
intTimer.Stop()
killTimer.Stop()
if timedOut {
return nil, ErrTimeout
}
return b, err
}

// ReadCommand runs command name with args and calls line for each line from its
Expand Down

0 comments on commit 4f5692d

Please sign in to comment.