Use cached state instead of runc state
.
Signed-off-by: Lantao Liu <lantaol@google.com>
This commit is contained in:
parent
a83ae30016
commit
18be6e3714
@ -69,3 +69,7 @@ func (s *deletedState) SetExited(status int) {
|
||||
func (s *deletedState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
|
||||
return nil, errors.Errorf("cannot exec in a deleted state")
|
||||
}
|
||||
|
||||
func (s *deletedState) Status(ctx context.Context) (string, error) {
|
||||
return "stopped", nil
|
||||
}
|
||||
|
@ -261,17 +261,5 @@ func (e *execProcess) Status(ctx context.Context) (string, error) {
|
||||
}
|
||||
e.mu.Lock()
|
||||
defer e.mu.Unlock()
|
||||
// if we don't have a pid(pid=0) then the exec process has just been created
|
||||
if e.pid.get() == 0 {
|
||||
return "created", nil
|
||||
}
|
||||
if e.pid.get() == StoppedPID {
|
||||
return "stopped", nil
|
||||
}
|
||||
// if we have a pid and it can be signaled, the process is running
|
||||
if err := unix.Kill(e.pid.get(), 0); err == nil {
|
||||
return "running", nil
|
||||
}
|
||||
// else if we have a pid but it can nolonger be signaled, it has stopped
|
||||
return "stopped", nil
|
||||
return e.execState.Status(ctx)
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ type execState interface {
|
||||
Delete(context.Context) error
|
||||
Kill(context.Context, uint32, bool) error
|
||||
SetExited(int)
|
||||
Status(context.Context) (string, error)
|
||||
}
|
||||
|
||||
type execCreatedState struct {
|
||||
@ -82,6 +83,10 @@ func (s *execCreatedState) SetExited(status int) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *execCreatedState) Status(ctx context.Context) (string, error) {
|
||||
return "created", nil
|
||||
}
|
||||
|
||||
type execRunningState struct {
|
||||
p *execProcess
|
||||
}
|
||||
@ -120,6 +125,10 @@ func (s *execRunningState) SetExited(status int) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *execRunningState) Status(ctx context.Context) (string, error) {
|
||||
return "running", nil
|
||||
}
|
||||
|
||||
type execStoppedState struct {
|
||||
p *execProcess
|
||||
}
|
||||
@ -157,3 +166,7 @@ func (s *execStoppedState) Kill(ctx context.Context, sig uint32, all bool) error
|
||||
func (s *execStoppedState) SetExited(status int) {
|
||||
// no op
|
||||
}
|
||||
|
||||
func (s *execStoppedState) Status(ctx context.Context) (string, error) {
|
||||
return "stopped", nil
|
||||
}
|
||||
|
@ -56,12 +56,14 @@ type Init struct {
|
||||
|
||||
WorkDir string
|
||||
|
||||
id string
|
||||
Bundle string
|
||||
console console.Console
|
||||
Platform stdio.Platform
|
||||
io *processIO
|
||||
runtime *runc.Runc
|
||||
id string
|
||||
Bundle string
|
||||
console console.Console
|
||||
Platform stdio.Platform
|
||||
io *processIO
|
||||
runtime *runc.Runc
|
||||
// pausing preserves the pausing state.
|
||||
pausing *atomicBool
|
||||
status int
|
||||
exited time.Time
|
||||
pid safePid
|
||||
@ -97,6 +99,7 @@ func New(id string, runtime *runc.Runc, stdio stdio.Stdio) *Init {
|
||||
p := &Init{
|
||||
id: id,
|
||||
runtime: runtime,
|
||||
pausing: new(atomicBool),
|
||||
stdio: stdio,
|
||||
status: 0,
|
||||
waitBlock: make(chan struct{}),
|
||||
@ -237,17 +240,14 @@ func (p *Init) ExitedAt() time.Time {
|
||||
|
||||
// Status of the process
|
||||
func (p *Init) Status(ctx context.Context) (string, error) {
|
||||
if p.pausing.get() {
|
||||
return "pausing", nil
|
||||
}
|
||||
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
c, err := p.runtime.State(ctx, p.id)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "does not exist") {
|
||||
return "stopped", nil
|
||||
}
|
||||
return "", p.runtimeError(err, "OCI runtime state failed")
|
||||
}
|
||||
return c.Status, nil
|
||||
return p.initState.Status(ctx)
|
||||
}
|
||||
|
||||
// Start the init process
|
||||
|
@ -37,6 +37,7 @@ type initState interface {
|
||||
Exec(context.Context, string, *ExecConfig) (Process, error)
|
||||
Kill(context.Context, uint32, bool) error
|
||||
SetExited(int)
|
||||
Status(context.Context) (string, error)
|
||||
}
|
||||
|
||||
type createdState struct {
|
||||
@ -103,6 +104,10 @@ func (s *createdState) Exec(ctx context.Context, path string, r *ExecConfig) (Pr
|
||||
return s.p.exec(ctx, path, r)
|
||||
}
|
||||
|
||||
func (s *createdState) Status(ctx context.Context) (string, error) {
|
||||
return "created", nil
|
||||
}
|
||||
|
||||
type createdCheckpointState struct {
|
||||
p *Init
|
||||
opts *runc.RestoreOpts
|
||||
@ -211,6 +216,10 @@ func (s *createdCheckpointState) Exec(ctx context.Context, path string, r *ExecC
|
||||
return nil, errors.Errorf("cannot exec in a created state")
|
||||
}
|
||||
|
||||
func (s *createdCheckpointState) Status(ctx context.Context) (string, error) {
|
||||
return "created", nil
|
||||
}
|
||||
|
||||
type runningState struct {
|
||||
p *Init
|
||||
}
|
||||
@ -228,6 +237,13 @@ func (s *runningState) transition(name string) error {
|
||||
}
|
||||
|
||||
func (s *runningState) Pause(ctx context.Context) error {
|
||||
s.p.pausing.set(true)
|
||||
// NOTE "pausing" will be returned in the short window
|
||||
// after `transition("paused")`, before `pausing` is reset
|
||||
// to false. That doesn't break the state machine, just
|
||||
// delays the "paused" state a little bit.
|
||||
defer s.p.pausing.set(false)
|
||||
|
||||
if err := s.p.runtime.Pause(ctx, s.p.id); err != nil {
|
||||
return s.p.runtimeError(err, "OCI runtime pause failed")
|
||||
}
|
||||
@ -271,6 +287,10 @@ func (s *runningState) Exec(ctx context.Context, path string, r *ExecConfig) (Pr
|
||||
return s.p.exec(ctx, path, r)
|
||||
}
|
||||
|
||||
func (s *runningState) Status(ctx context.Context) (string, error) {
|
||||
return "running", nil
|
||||
}
|
||||
|
||||
type pausedState struct {
|
||||
p *Init
|
||||
}
|
||||
@ -335,6 +355,10 @@ func (s *pausedState) Exec(ctx context.Context, path string, r *ExecConfig) (Pro
|
||||
return nil, errors.Errorf("cannot exec in a paused state")
|
||||
}
|
||||
|
||||
func (s *pausedState) Status(ctx context.Context) (string, error) {
|
||||
return "paused", nil
|
||||
}
|
||||
|
||||
type stoppedState struct {
|
||||
p *Init
|
||||
}
|
||||
@ -387,3 +411,7 @@ func (s *stoppedState) SetExited(status int) {
|
||||
func (s *stoppedState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
|
||||
return nil, errors.Errorf("cannot exec in a stopped state")
|
||||
}
|
||||
|
||||
func (s *stoppedState) Status(ctx context.Context) (string, error) {
|
||||
return "stopped", nil
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
@ -62,6 +63,20 @@ func (s *safePid) set(pid int) {
|
||||
s.Unlock()
|
||||
}
|
||||
|
||||
type atomicBool int32
|
||||
|
||||
func (ab *atomicBool) set(b bool) {
|
||||
if b {
|
||||
atomic.StoreInt32((*int32)(ab), 1)
|
||||
} else {
|
||||
atomic.StoreInt32((*int32)(ab), 0)
|
||||
}
|
||||
}
|
||||
|
||||
func (ab *atomicBool) get() bool {
|
||||
return atomic.LoadInt32((*int32)(ab)) == 1
|
||||
}
|
||||
|
||||
// TODO(mlaventure): move to runc package?
|
||||
func getLastRuntimeError(r *runc.Runc) (string, error) {
|
||||
if r.Log == "" {
|
||||
|
Loading…
Reference in New Issue
Block a user