Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(49)

Side by Side Diff: ct/go/util/util.go

Issue 1302513006: Reland of Add a library for running external commands, providing timeouts and test injection. (Closed) Base URL: https://skia.googlesource.com/buildbot@master
Patch Set: Fix bug with nil io.Writer. Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ct/go/adb/adb.go ('k') | go/exec/exec.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Utility that contains methods for both CT master and worker scripts. 1 // Utility that contains methods for both CT master and worker scripts.
2 package util 2 package util
3 3
4 import ( 4 import (
5 "bufio" 5 "bufio"
6 "fmt" 6 "fmt"
7 "io"
7 "io/ioutil" 8 "io/ioutil"
8 "os" 9 "os"
9 "os/exec"
10 "path/filepath" 10 "path/filepath"
11 "strconv" 11 "strconv"
12 "strings"
13 "time" 12 "time"
14 13
14 "go.skia.org/infra/go/exec"
15 "go.skia.org/infra/go/util" 15 "go.skia.org/infra/go/util"
16 16
17 "github.com/skia-dev/glog" 17 "github.com/skia-dev/glog"
18 ) 18 )
19 19
20 const ( 20 const (
21 MAX_SYNC_TRIES = 3 21 MAX_SYNC_TRIES = 3
22 ) 22 )
23 23
24 // GetCTWorkers returns an array of all CT workers. 24 // GetCTWorkers returns an array of all CT workers.
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 if err := os.Remove(taskFilePath); err != nil { 79 if err := os.Remove(taskFilePath); err != nil {
80 glog.Errorf("Could not delete %s: %s", taskFilePath, err) 80 glog.Errorf("Could not delete %s: %s", taskFilePath, err)
81 } 81 }
82 } 82 }
83 83
84 func TimeTrack(start time.Time, name string) { 84 func TimeTrack(start time.Time, name string) {
85 elapsed := time.Since(start) 85 elapsed := time.Since(start)
86 glog.Infof("===== %s took %s =====", name, elapsed) 86 glog.Infof("===== %s took %s =====", name, elapsed)
87 } 87 }
88 88
89 // WriteLog implements the io.Writer interface and writes to glog and an output 89 // ExecuteCmd executes the specified binary with the specified args and env. Std out and Stderr are
90 // file (if specified). 90 // written to stdout and stderr respectively if specified. If not specified then Stdout and Stderr
91 type WriteLog struct { 91 // will be outputted only to glog.
92 » LogFunc func(format string, args ...interface{}) 92 func ExecuteCmd(binary string, args, env []string, timeout time.Duration, stdout , stderr io.Writer) error {
93 » OutputFile *os.File 93 » return exec.Run(&exec.Command{
94 } 94 » » Name: binary,
95 95 » » Args: args,
96 func (wl WriteLog) Write(p []byte) (n int, err error) { 96 » » Env: env,
97 » wl.LogFunc("%s", string(p)) 97 » » InheritPath: true,
98 » // Write to file if specified. 98 » » Timeout: timeout,
99 » if wl.OutputFile != nil { 99 » » LogStdout: true,
100 » » if n, err := wl.OutputFile.WriteString(string(p)); err != nil { 100 » » Stdout: stdout,
101 » » » glog.Errorf("Could not write to %s: %s", wl.OutputFile.N ame(), err) 101 » » LogStderr: true,
102 » » » return n, err 102 » » Stderr: stderr,
103 » » } 103 » })
104 » }
105 » return len(p), nil
106 }
107
108 // ExecuteCmd executes the specified binary with the specified args and env.
109 // Stdout and Stderr are written to stdoutFile and stderrFile respectively if
110 // specified. If not specified then stdout and stderr will be outputted only to
111 // glog. Note: It is the responsibility of the caller to close stdoutFile and
112 // stderrFile.
113 func ExecuteCmd(binary string, args, env []string, timeout time.Duration, stdout File, stderrFile *os.File) error {
114 » // Add the current PATH to the env.
115 » env = append(env, "PATH="+os.Getenv("PATH"))
116
117 » // Create the cmd obj.
118 » cmd := exec.Command(binary, args...)
119 » cmd.Env = env
120
121 » // Attach WriteLog to command.
122 » cmd.Stdout = WriteLog{LogFunc: glog.Infof, OutputFile: stdoutFile}
123 » cmd.Stderr = WriteLog{LogFunc: glog.Errorf, OutputFile: stderrFile}
124
125 » // Execute cmd.
126 » glog.Infof("Executing %s %s", strings.Join(cmd.Env, " "), strings.Join(c md.Args, " "))
127 » util.LogErr(cmd.Start())
128 » done := make(chan error)
129 » go func() {
130 » » done <- cmd.Wait()
131 » }()
132 » select {
133 » case <-time.After(timeout):
134 » » if err := cmd.Process.Kill(); err != nil {
135 » » » return fmt.Errorf("Failed to kill timed out process: %s" , err)
136 » » }
137 » » <-done // allow goroutine to exit
138 » » glog.Errorf("Command killed since it took longer than %f secs", timeout.Seconds())
139 » » return fmt.Errorf("Command killed since it took longer than %f s ecs", timeout.Seconds())
140 » case err := <-done:
141 » » if err != nil {
142 » » » return fmt.Errorf("Process done with error: %s", err)
143 » » }
144 » }
145 » return nil
146 } 104 }
147 105
148 // SyncDir runs "git pull" and "gclient sync" on the specified directory. 106 // SyncDir runs "git pull" and "gclient sync" on the specified directory.
149 func SyncDir(dir string) error { 107 func SyncDir(dir string) error {
150 err := os.Chdir(dir) 108 err := os.Chdir(dir)
151 if err != nil { 109 if err != nil {
152 return fmt.Errorf("Could not chdir to %s: %s", dir, err) 110 return fmt.Errorf("Could not chdir to %s: %s", dir, err)
153 } 111 }
154 112
155 for i := 0; i < MAX_SYNC_TRIES; i++ { 113 for i := 0; i < MAX_SYNC_TRIES; i++ {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 } 176 }
219 177
220 // CleanTmpDir deletes all tmp files from the caller because telemetry tends to 178 // CleanTmpDir deletes all tmp files from the caller because telemetry tends to
221 // generate a lot of temporary artifacts there and they take up root disk space. 179 // generate a lot of temporary artifacts there and they take up root disk space.
222 func CleanTmpDir() { 180 func CleanTmpDir() {
223 files, _ := ioutil.ReadDir(os.TempDir()) 181 files, _ := ioutil.ReadDir(os.TempDir())
224 for _, f := range files { 182 for _, f := range files {
225 util.RemoveAll(filepath.Join(os.TempDir(), f.Name())) 183 util.RemoveAll(filepath.Join(os.TempDir(), f.Name()))
226 } 184 }
227 } 185 }
OLDNEW
« no previous file with comments | « ct/go/adb/adb.go ('k') | go/exec/exec.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698