diff --git a/runtime/process.go b/runtime/process.go index cba1eab..a56faa5 100644 --- a/runtime/process.go +++ b/runtime/process.go @@ -36,7 +36,7 @@ type Process interface { ExitFD() int // ExitStatus returns the exit status of the process or an error if it // has not exited - ExitStatus() (int, error) + ExitStatus() (uint32, error) // Spec returns the process spec that created the process Spec() specs.ProcessSpec // Signal sends the provided signal to the process @@ -228,31 +228,31 @@ func (p *process) Resize(w, h int) error { return err } -func (p *process) updateExitStatusFile(status int) (int, error) { +func (p *process) updateExitStatusFile(status uint32) (uint32, error) { p.stateLock.Lock() p.state = Stopped p.stateLock.Unlock() - err := ioutil.WriteFile(filepath.Join(p.root, ExitStatusFile), []byte(fmt.Sprintf("%d", status)), 0644) + err := ioutil.WriteFile(filepath.Join(p.root, ExitStatusFile), []byte(fmt.Sprintf("%u", status)), 0644) return status, err } -func (p *process) handleSigkilledShim(rst int, rerr error) (int, error) { +func (p *process) handleSigkilledShim(rst uint32, rerr error) (uint32, error) { if p.cmd == nil || p.cmd.Process == nil { e := unix.Kill(p.pid, 0) if e == syscall.ESRCH { logrus.Warnf("containerd: %s:%s (pid %d) does not exist", p.container.id, p.id, p.pid) // The process died while containerd was down (probably of // SIGKILL, but no way to be sure) - return p.updateExitStatusFile(255) + return p.updateExitStatusFile(UnknownStatus) } // If it's not the same process, just mark it stopped and set - // the status to 255 + // the status to the UnknownStatus value (i.e. 255) if same, err := p.isSameProcess(); !same { logrus.Warnf("containerd: %s:%s (pid %d) is not the same process anymore (%v)", p.container.id, p.id, p.pid, err) // Create the file so we get the exit event generated once monitor kicks in // without having to go through all this process again - return p.updateExitStatusFile(255) + return p.updateExitStatusFile(UnknownStatus) } ppid, err := readProcStatField(p.pid, 4) @@ -263,7 +263,7 @@ func (p *process) handleSigkilledShim(rst int, rerr error) (int, error) { logrus.Warnf("containerd: %s:%s shim died, killing associated process", p.container.id, p.id) unix.Kill(p.pid, syscall.SIGKILL) if err != nil && err != syscall.ESRCH { - return 255, fmt.Errorf("containerd: unable to SIGKILL %s:%s (pid %v): %v", p.container.id, p.id, p.pid, err) + return UnknownStatus, fmt.Errorf("containerd: unable to SIGKILL %s:%s (pid %v): %v", p.container.id, p.id, p.pid, err) } // wait for the process to die @@ -276,7 +276,7 @@ func (p *process) handleSigkilledShim(rst int, rerr error) (int, error) { } // Create the file so we get the exit event generated once monitor kicks in // without having to go through all this process again - return p.updateExitStatusFile(128 + int(syscall.SIGKILL)) + return p.updateExitStatusFile(128 + uint32(syscall.SIGKILL)) } return rst, rerr @@ -296,7 +296,7 @@ func (p *process) handleSigkilledShim(rst int, rerr error) (int, error) { logrus.Debugf("containerd: ExitStatus(container: %s, process: %s): shim was SIGKILL'ed reaping its child with pid %d", p.container.id, p.id, p.pid) rerr = nil - rst = 128 + int(shimStatus.Signal()) + rst = 128 + uint32(shimStatus.Signal()) p.stateLock.Lock() p.state = Stopped @@ -306,7 +306,7 @@ func (p *process) handleSigkilledShim(rst int, rerr error) (int, error) { return rst, rerr } -func (p *process) ExitStatus() (rst int, rerr error) { +func (p *process) ExitStatus() (rst uint32, rerr error) { data, err := ioutil.ReadFile(filepath.Join(p.root, ExitStatusFile)) defer func() { if rerr != nil { @@ -315,17 +315,19 @@ func (p *process) ExitStatus() (rst int, rerr error) { }() if err != nil { if os.IsNotExist(err) { - return -1, ErrProcessNotExited + return UnknownStatus, ErrProcessNotExited } - return -1, err + return UnknownStatus, err } if len(data) == 0 { - return -1, ErrProcessNotExited + return UnknownStatus, ErrProcessNotExited } p.stateLock.Lock() p.state = Stopped p.stateLock.Unlock() - return strconv.Atoi(string(data)) + + i, err := strconv.ParseUint(string(data), 10, 32) + return uint32(i), err } func (p *process) Spec() specs.ProcessSpec { diff --git a/runtime/runtime.go b/runtime/runtime.go index eecb545..ef5dad9 100644 --- a/runtime/runtime.go +++ b/runtime/runtime.go @@ -47,6 +47,10 @@ const ( // StartTimeFile holds the name of the file in which the process // start time is saved StartTimeFile = "starttime" + + // UnknownStatus is the value returned when a process exit + // status cannot be determined + UnknownStatus = 255 ) // Checkpoint holds information regarding a container checkpoint diff --git a/supervisor/delete.go b/supervisor/delete.go index 95720d5..72dbc80 100644 --- a/supervisor/delete.go +++ b/supervisor/delete.go @@ -11,7 +11,7 @@ import ( type DeleteTask struct { baseTask ID string - Status int + Status uint32 PID string NoEvent bool Process runtime.Process diff --git a/supervisor/exit.go b/supervisor/exit.go index e20ee47..faf92bf 100644 --- a/supervisor/exit.go +++ b/supervisor/exit.go @@ -63,7 +63,7 @@ type ExecExitTask struct { baseTask ID string PID string - Status int + Status uint32 Process runtime.Process } diff --git a/supervisor/sort_test.go b/supervisor/sort_test.go index 9438f0a..9a0467c 100644 --- a/supervisor/sort_test.go +++ b/supervisor/sort_test.go @@ -46,8 +46,8 @@ func (p *testProcess) ExitFD() int { return -1 } -func (p *testProcess) ExitStatus() (int, error) { - return -1, nil +func (p *testProcess) ExitStatus() (uint32, error) { + return runtime.UnknownStatus, nil } func (p *testProcess) Container() runtime.Container { diff --git a/supervisor/supervisor.go b/supervisor/supervisor.go index 9055ac0..c1232f2 100644 --- a/supervisor/supervisor.go +++ b/supervisor/supervisor.go @@ -186,7 +186,7 @@ type Event struct { Type string `json:"type"` Timestamp time.Time `json:"timestamp"` PID string `json:"pid,omitempty"` - Status int `json:"status,omitempty"` + Status uint32 `json:"status,omitempty"` } // Events returns an event channel that external consumers can use to receive updates