diff --git a/client/driver/exec.go b/client/driver/exec.go index 136016113..eef38d2b9 100644 --- a/client/driver/exec.go +++ b/client/driver/exec.go @@ -283,7 +283,7 @@ func (h *execHandle) run() { h.logger.Printf("[ERR] driver.exec: unmounting dev,proc and alloc dirs failed: %v", e) } } - h.waitCh <- cstructs.NewWaitResult(ps.ExitCode, 0, err) + h.waitCh <- cstructs.NewWaitResult(ps.ExitCode, ps.Signal, err) close(h.waitCh) // Remove services if err := h.executor.DeregisterServices(); err != nil { diff --git a/client/driver/executor/executor.go b/client/driver/executor/executor.go index 434d9c62b..3d57f92a8 100644 --- a/client/driver/executor/executor.go +++ b/client/driver/executor/executor.go @@ -324,12 +324,16 @@ func (e *UniversalExecutor) wait() { return } exitCode := 1 + var signal int if exitErr, ok := err.(*exec.ExitError); ok { if status, ok := exitErr.Sys().(syscall.WaitStatus); ok { exitCode = status.ExitStatus() + if status.Signaled() { + signal = int(status.Signal()) + } } } - e.exitState = &ProcessState{Pid: 0, ExitCode: exitCode, Time: time.Now()} + e.exitState = &ProcessState{Pid: 0, ExitCode: exitCode, Signal: signal, Time: time.Now()} } var ( diff --git a/client/driver/executor/executor_test.go b/client/driver/executor/executor_test.go index c80fa77f6..cf54bea06 100644 --- a/client/driver/executor/executor_test.go +++ b/client/driver/executor/executor_test.go @@ -7,6 +7,7 @@ import ( "path/filepath" "reflect" "strings" + "syscall" "testing" "time" @@ -118,6 +119,36 @@ func TestExecutor_Start_Wait(t *testing.T) { } } +func TestExecutor_WaitExitSignal(t *testing.T) { + execCmd := ExecCommand{Cmd: "/bin/sleep", Args: []string{"10000"}} + ctx := testExecutorContext(t) + defer ctx.AllocDir.Destroy() + executor := NewExecutor(log.New(os.Stdout, "", log.LstdFlags)) + ps, err := executor.LaunchCmd(&execCmd, ctx) + if err != nil { + t.Fatalf("err: %v", err) + } + + go func() { + time.Sleep(1 * time.Second) + proc, err := os.FindProcess(ps.Pid) + if err != nil { + t.Fatalf("err: %v", err) + } + if err := proc.Signal(syscall.SIGKILL); err != nil { + t.Fatalf("err: %v", err) + } + }() + + ps, err = executor.Wait() + if err != nil { + t.Fatalf("err: %v", err) + } + if ps.Signal != int(syscall.SIGKILL) { + t.Fatalf("expected signal: %v, actual: %v", int(syscall.SIGKILL), ps.Signal) + } +} + func TestExecutor_IsolationAndConstraints(t *testing.T) { testutil.ExecCompatible(t) diff --git a/client/driver/java.go b/client/driver/java.go index 5fa2909c7..b56079cd7 100644 --- a/client/driver/java.go +++ b/client/driver/java.go @@ -352,7 +352,7 @@ func (h *javaHandle) run() { h.logger.Printf("[ERR] driver.java: unmounting dev,proc and alloc dirs failed: %v", e) } } - h.waitCh <- &cstructs.WaitResult{ExitCode: ps.ExitCode, Signal: 0, Err: err} + h.waitCh <- &cstructs.WaitResult{ExitCode: ps.ExitCode, Signal: ps.Signal, Err: err} close(h.waitCh) // Remove services diff --git a/client/driver/qemu.go b/client/driver/qemu.go index 31dc63f36..2c853ec46 100644 --- a/client/driver/qemu.go +++ b/client/driver/qemu.go @@ -346,7 +346,7 @@ func (h *qemuHandle) run() { } } close(h.doneCh) - h.waitCh <- &cstructs.WaitResult{ExitCode: ps.ExitCode, Signal: 0, Err: err} + h.waitCh <- &cstructs.WaitResult{ExitCode: ps.ExitCode, Signal: ps.Signal, Err: err} close(h.waitCh) // Remove services if err := h.executor.DeregisterServices(); err != nil { diff --git a/client/driver/raw_exec.go b/client/driver/raw_exec.go index c9610cdc2..5fc3b33e4 100644 --- a/client/driver/raw_exec.go +++ b/client/driver/raw_exec.go @@ -254,7 +254,7 @@ func (h *rawExecHandle) run() { h.logger.Printf("[ERR] driver.raw_exec: unmounting dev,proc and alloc dirs failed: %v", e) } } - h.waitCh <- &cstructs.WaitResult{ExitCode: ps.ExitCode, Signal: 0, Err: err} + h.waitCh <- &cstructs.WaitResult{ExitCode: ps.ExitCode, Signal: ps.Signal, Err: err} close(h.waitCh) // Remove services if err := h.executor.DeregisterServices(); err != nil {