"os/exec"
"path"
"path/filepath"
+ "strconv"
"strings"
"sync"
"syscall"
FdStatus.Write([]byte{StatusRun})
}
+ var finished time.Time
+ var exitErr *exec.ExitError
started := time.Now()
runErr.Started = &started
fdStdout, err = os.OpenFile(stdoutPath, os.O_RDWR, os.FileMode(0666))
defer func() {
jsRelease(shCtx, jsToken)
- lockRelease()
fdDep.Close()
fdStdout.Close()
if fdStderr != nil {
fdStderr.Close()
+ logRecPath := path.Join(redoDir, tgt+LogSuffix+DepSuffix)
+ if fdStderr, err = os.OpenFile(
+ logRecPath,
+ os.O_WRONLY|os.O_CREATE,
+ os.FileMode(0666),
+ ); err == nil {
+ fdStderr.Truncate(0)
+ fields := []recfile.Field{
+ {Name: "Build", Value: BuildUUID},
+ {Name: "PID", Value: strconv.Itoa(cmd.Process.Pid)},
+ {Name: "PPID", Value: strconv.Itoa(os.Getpid())},
+ {Name: "Cwd", Value: cwd},
+ }
+ ts := new(tai64n.TAI64N)
+ ts.FromTime(started)
+ fields = append(fields,
+ recfile.Field{Name: "Started", Value: tai64n.Encode(ts[:])},
+ )
+ ts.FromTime(finished)
+ fields = append(fields,
+ recfile.Field{Name: "Finished", Value: tai64n.Encode(ts[:])})
+ fields = append(fields, recfile.Field{
+ Name: "Duration",
+ Value: strconv.FormatInt(finished.Sub(started).Nanoseconds(), 10),
+ })
+ fields = append(fields, recfile.Field{Name: "Cmd", Value: cmdName})
+ for _, arg := range args {
+ fields = append(fields, recfile.Field{Name: "Cmd", Value: arg})
+ }
+ for _, e := range cmd.Env {
+ fields = append(fields, recfile.Field{Name: "Env", Value: e})
+ }
+ if exitErr != nil {
+ fields = append(fields, recfile.Field{
+ Name: "ExitCode",
+ Value: strconv.Itoa(exitErr.ProcessState.ExitCode()),
+ })
+ }
+ w := bufio.NewWriter(fdStderr)
+ _, err = recfile.NewWriter(w).WriteFields(fields...)
+ w.Flush()
+ fdStderr.Close()
+ if err != nil {
+ os.Remove(logRecPath)
+ }
+ }
}
+ lockRelease()
os.Remove(fdDep.Name())
os.Remove(fdStdout.Name())
os.Remove(tmpPath)
// Wait for job completion
<-stderrTerm
err = cmd.Wait()
- finished := time.Now()
+ finished = time.Now()
runErr.Finished = &finished
if err != nil {
+ // Try to commit .rec anyway
+ if !NoSync {
+ fdDep.Sync()
+ }
+ os.Rename(fdDep.Name(), path.Join(redoDir, tgt+DepSuffix))
+ if !NoSync {
+ err = syncDir(redoDir)
+ }
+
+ exitErr = err.(*exec.ExitError)
runErr.Err = err
errs <- runErr
return