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) {
|
func (s *deletedState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
|
||||||
return nil, errors.Errorf("cannot exec in a deleted state")
|
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()
|
e.mu.Lock()
|
||||||
defer e.mu.Unlock()
|
defer e.mu.Unlock()
|
||||||
// if we don't have a pid(pid=0) then the exec process has just been created
|
return e.execState.Status(ctx)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ type execState interface {
|
|||||||
Delete(context.Context) error
|
Delete(context.Context) error
|
||||||
Kill(context.Context, uint32, bool) error
|
Kill(context.Context, uint32, bool) error
|
||||||
SetExited(int)
|
SetExited(int)
|
||||||
|
Status(context.Context) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type execCreatedState struct {
|
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 {
|
type execRunningState struct {
|
||||||
p *execProcess
|
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 {
|
type execStoppedState struct {
|
||||||
p *execProcess
|
p *execProcess
|
||||||
}
|
}
|
||||||
@ -157,3 +166,7 @@ func (s *execStoppedState) Kill(ctx context.Context, sig uint32, all bool) error
|
|||||||
func (s *execStoppedState) SetExited(status int) {
|
func (s *execStoppedState) SetExited(status int) {
|
||||||
// no op
|
// no op
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *execStoppedState) Status(ctx context.Context) (string, error) {
|
||||||
|
return "stopped", nil
|
||||||
|
}
|
||||||
|
@ -62,6 +62,8 @@ type Init struct {
|
|||||||
Platform stdio.Platform
|
Platform stdio.Platform
|
||||||
io *processIO
|
io *processIO
|
||||||
runtime *runc.Runc
|
runtime *runc.Runc
|
||||||
|
// pausing preserves the pausing state.
|
||||||
|
pausing *atomicBool
|
||||||
status int
|
status int
|
||||||
exited time.Time
|
exited time.Time
|
||||||
pid safePid
|
pid safePid
|
||||||
@ -97,6 +99,7 @@ func New(id string, runtime *runc.Runc, stdio stdio.Stdio) *Init {
|
|||||||
p := &Init{
|
p := &Init{
|
||||||
id: id,
|
id: id,
|
||||||
runtime: runtime,
|
runtime: runtime,
|
||||||
|
pausing: new(atomicBool),
|
||||||
stdio: stdio,
|
stdio: stdio,
|
||||||
status: 0,
|
status: 0,
|
||||||
waitBlock: make(chan struct{}),
|
waitBlock: make(chan struct{}),
|
||||||
@ -237,17 +240,14 @@ func (p *Init) ExitedAt() time.Time {
|
|||||||
|
|
||||||
// Status of the process
|
// Status of the process
|
||||||
func (p *Init) Status(ctx context.Context) (string, error) {
|
func (p *Init) Status(ctx context.Context) (string, error) {
|
||||||
|
if p.pausing.get() {
|
||||||
|
return "pausing", nil
|
||||||
|
}
|
||||||
|
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
defer p.mu.Unlock()
|
defer p.mu.Unlock()
|
||||||
|
|
||||||
c, err := p.runtime.State(ctx, p.id)
|
return p.initState.Status(ctx)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the init process
|
// Start the init process
|
||||||
|
@ -37,6 +37,7 @@ type initState interface {
|
|||||||
Exec(context.Context, string, *ExecConfig) (Process, error)
|
Exec(context.Context, string, *ExecConfig) (Process, error)
|
||||||
Kill(context.Context, uint32, bool) error
|
Kill(context.Context, uint32, bool) error
|
||||||
SetExited(int)
|
SetExited(int)
|
||||||
|
Status(context.Context) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type createdState struct {
|
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)
|
return s.p.exec(ctx, path, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *createdState) Status(ctx context.Context) (string, error) {
|
||||||
|
return "created", nil
|
||||||
|
}
|
||||||
|
|
||||||
type createdCheckpointState struct {
|
type createdCheckpointState struct {
|
||||||
p *Init
|
p *Init
|
||||||
opts *runc.RestoreOpts
|
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")
|
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 {
|
type runningState struct {
|
||||||
p *Init
|
p *Init
|
||||||
}
|
}
|
||||||
@ -228,6 +237,13 @@ func (s *runningState) transition(name string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *runningState) Pause(ctx context.Context) 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 {
|
if err := s.p.runtime.Pause(ctx, s.p.id); err != nil {
|
||||||
return s.p.runtimeError(err, "OCI runtime pause failed")
|
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)
|
return s.p.exec(ctx, path, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *runningState) Status(ctx context.Context) (string, error) {
|
||||||
|
return "running", nil
|
||||||
|
}
|
||||||
|
|
||||||
type pausedState struct {
|
type pausedState struct {
|
||||||
p *Init
|
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")
|
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 {
|
type stoppedState struct {
|
||||||
p *Init
|
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) {
|
func (s *stoppedState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
|
||||||
return nil, errors.Errorf("cannot exec in a stopped state")
|
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"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
@ -62,6 +63,20 @@ func (s *safePid) set(pid int) {
|
|||||||
s.Unlock()
|
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?
|
// TODO(mlaventure): move to runc package?
|
||||||
func getLastRuntimeError(r *runc.Runc) (string, error) {
|
func getLastRuntimeError(r *runc.Runc) (string, error) {
|
||||||
if r.Log == "" {
|
if r.Log == "" {
|
||||||
|
Loading…
Reference in New Issue
Block a user