Merge "[Reland] lucifer: capture non-zero exit code in deployment."
diff --git a/src/lucifer/cmd/lucifer/deploytask.go b/src/lucifer/cmd/lucifer/deploytask.go
index 6a73a6f..995a449 100644
--- a/src/lucifer/cmd/lucifer/deploytask.go
+++ b/src/lucifer/cmd/lucifer/deploytask.go
@@ -120,6 +120,8 @@
reason = fmt.Errorf("process failed to start")
case r.Aborted:
reason = fmt.Errorf("process aborted")
+ case r.ExitStatus != 0:
+ reason = fmt.Errorf("process fail with exit code %d", r.ExitStatus)
}
switch {
case reason == nil:
diff --git a/src/lucifer/osutil/osutil.go b/src/lucifer/osutil/osutil.go
index d4e8f96..2bef5e6 100644
--- a/src/lucifer/osutil/osutil.go
+++ b/src/lucifer/osutil/osutil.go
@@ -20,6 +20,22 @@
// Started is true if the process was started successfully.
Started bool
Aborted bool
+ // ExitStatus only makes sense if Started is true.
+ ExitStatus int
+}
+
+func getCmdExitStatus(err error) int {
+ if ee, ok := err.(*exec.ExitError); ok {
+ // Cannot use ee.ProcessState.ExitCode() as ExitCode is not supported until go1.12.
+ // https://golang.org/pkg/os/#ProcessState.ExitCode
+ // But chroot has go version 1.11.2.
+ if status, ok := ee.ProcessState.Sys().(syscall.WaitStatus); ok {
+ return status.ExitStatus()
+ } else {
+ return -1
+ }
+ }
+ return -1
}
// RunWithAbort runs an exec.Cmd with context cancellation/aborting.
@@ -36,7 +52,9 @@
r.Started = true
exited := make(chan struct{})
go func() {
- _ = cmd.Wait()
+ if err := cmd.Wait(); err != nil {
+ r.ExitStatus = getCmdExitStatus(err)
+ }
close(exited)
}()
select {