Skip to content

Commit 5028701

Browse files
Merge pull request #3753 from thaJeztah/1.3_backport_avoid_unnecessary_runc_state
[release/1.3 backport] Use cached state instead of `runc state`.
2 parents e3d2b60 + 9abfc70 commit 5028701

6 files changed

Lines changed: 75 additions & 27 deletions

File tree

pkg/process/deleted_state.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,7 @@ func (s *deletedState) SetExited(status int) {
6969
func (s *deletedState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
7070
return nil, errors.Errorf("cannot exec in a deleted state")
7171
}
72+
73+
func (s *deletedState) Status(ctx context.Context) (string, error) {
74+
return "stopped", nil
75+
}

pkg/process/exec.go

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -261,17 +261,5 @@ func (e *execProcess) Status(ctx context.Context) (string, error) {
261261
}
262262
e.mu.Lock()
263263
defer e.mu.Unlock()
264-
// if we don't have a pid(pid=0) then the exec process has just been created
265-
if e.pid.get() == 0 {
266-
return "created", nil
267-
}
268-
if e.pid.get() == StoppedPID {
269-
return "stopped", nil
270-
}
271-
// if we have a pid and it can be signaled, the process is running
272-
if err := unix.Kill(e.pid.get(), 0); err == nil {
273-
return "running", nil
274-
}
275-
// else if we have a pid but it can nolonger be signaled, it has stopped
276-
return "stopped", nil
264+
return e.execState.Status(ctx)
277265
}

pkg/process/exec_state.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ type execState interface {
3131
Delete(context.Context) error
3232
Kill(context.Context, uint32, bool) error
3333
SetExited(int)
34+
Status(context.Context) (string, error)
3435
}
3536

3637
type execCreatedState struct {
@@ -82,6 +83,10 @@ func (s *execCreatedState) SetExited(status int) {
8283
}
8384
}
8485

86+
func (s *execCreatedState) Status(ctx context.Context) (string, error) {
87+
return "created", nil
88+
}
89+
8590
type execRunningState struct {
8691
p *execProcess
8792
}
@@ -120,6 +125,10 @@ func (s *execRunningState) SetExited(status int) {
120125
}
121126
}
122127

128+
func (s *execRunningState) Status(ctx context.Context) (string, error) {
129+
return "running", nil
130+
}
131+
123132
type execStoppedState struct {
124133
p *execProcess
125134
}
@@ -157,3 +166,7 @@ func (s *execStoppedState) Kill(ctx context.Context, sig uint32, all bool) error
157166
func (s *execStoppedState) SetExited(status int) {
158167
// no op
159168
}
169+
170+
func (s *execStoppedState) Status(ctx context.Context) (string, error) {
171+
return "stopped", nil
172+
}

pkg/process/init.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,14 @@ type Init struct {
5656

5757
WorkDir string
5858

59-
id string
60-
Bundle string
61-
console console.Console
62-
Platform stdio.Platform
63-
io *processIO
64-
runtime *runc.Runc
59+
id string
60+
Bundle string
61+
console console.Console
62+
Platform stdio.Platform
63+
io *processIO
64+
runtime *runc.Runc
65+
// pausing preserves the pausing state.
66+
pausing *atomicBool
6567
status int
6668
exited time.Time
6769
pid safePid
@@ -97,6 +99,7 @@ func New(id string, runtime *runc.Runc, stdio stdio.Stdio) *Init {
9799
p := &Init{
98100
id: id,
99101
runtime: runtime,
102+
pausing: new(atomicBool),
100103
stdio: stdio,
101104
status: 0,
102105
waitBlock: make(chan struct{}),
@@ -237,17 +240,14 @@ func (p *Init) ExitedAt() time.Time {
237240

238241
// Status of the process
239242
func (p *Init) Status(ctx context.Context) (string, error) {
243+
if p.pausing.get() {
244+
return "pausing", nil
245+
}
246+
240247
p.mu.Lock()
241248
defer p.mu.Unlock()
242249

243-
c, err := p.runtime.State(ctx, p.id)
244-
if err != nil {
245-
if strings.Contains(err.Error(), "does not exist") {
246-
return "stopped", nil
247-
}
248-
return "", p.runtimeError(err, "OCI runtime state failed")
249-
}
250-
return c.Status, nil
250+
return p.initState.Status(ctx)
251251
}
252252

253253
// Start the init process

pkg/process/init_state.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ type initState interface {
3737
Exec(context.Context, string, *ExecConfig) (Process, error)
3838
Kill(context.Context, uint32, bool) error
3939
SetExited(int)
40+
Status(context.Context) (string, error)
4041
}
4142

4243
type createdState struct {
@@ -103,6 +104,10 @@ func (s *createdState) Exec(ctx context.Context, path string, r *ExecConfig) (Pr
103104
return s.p.exec(ctx, path, r)
104105
}
105106

107+
func (s *createdState) Status(ctx context.Context) (string, error) {
108+
return "created", nil
109+
}
110+
106111
type createdCheckpointState struct {
107112
p *Init
108113
opts *runc.RestoreOpts
@@ -211,6 +216,10 @@ func (s *createdCheckpointState) Exec(ctx context.Context, path string, r *ExecC
211216
return nil, errors.Errorf("cannot exec in a created state")
212217
}
213218

219+
func (s *createdCheckpointState) Status(ctx context.Context) (string, error) {
220+
return "created", nil
221+
}
222+
214223
type runningState struct {
215224
p *Init
216225
}
@@ -228,6 +237,13 @@ func (s *runningState) transition(name string) error {
228237
}
229238

230239
func (s *runningState) Pause(ctx context.Context) error {
240+
s.p.pausing.set(true)
241+
// NOTE "pausing" will be returned in the short window
242+
// after `transition("paused")`, before `pausing` is reset
243+
// to false. That doesn't break the state machine, just
244+
// delays the "paused" state a little bit.
245+
defer s.p.pausing.set(false)
246+
231247
if err := s.p.runtime.Pause(ctx, s.p.id); err != nil {
232248
return s.p.runtimeError(err, "OCI runtime pause failed")
233249
}
@@ -271,6 +287,10 @@ func (s *runningState) Exec(ctx context.Context, path string, r *ExecConfig) (Pr
271287
return s.p.exec(ctx, path, r)
272288
}
273289

290+
func (s *runningState) Status(ctx context.Context) (string, error) {
291+
return "running", nil
292+
}
293+
274294
type pausedState struct {
275295
p *Init
276296
}
@@ -335,6 +355,10 @@ func (s *pausedState) Exec(ctx context.Context, path string, r *ExecConfig) (Pro
335355
return nil, errors.Errorf("cannot exec in a paused state")
336356
}
337357

358+
func (s *pausedState) Status(ctx context.Context) (string, error) {
359+
return "paused", nil
360+
}
361+
338362
type stoppedState struct {
339363
p *Init
340364
}
@@ -387,3 +411,7 @@ func (s *stoppedState) SetExited(status int) {
387411
func (s *stoppedState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
388412
return nil, errors.Errorf("cannot exec in a stopped state")
389413
}
414+
415+
func (s *stoppedState) Status(ctx context.Context) (string, error) {
416+
return "stopped", nil
417+
}

pkg/process/utils.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"path/filepath"
2828
"strings"
2929
"sync"
30+
"sync/atomic"
3031
"time"
3132

3233
"github.com/containerd/containerd/errdefs"
@@ -62,6 +63,20 @@ func (s *safePid) set(pid int) {
6263
s.Unlock()
6364
}
6465

66+
type atomicBool int32
67+
68+
func (ab *atomicBool) set(b bool) {
69+
if b {
70+
atomic.StoreInt32((*int32)(ab), 1)
71+
} else {
72+
atomic.StoreInt32((*int32)(ab), 0)
73+
}
74+
}
75+
76+
func (ab *atomicBool) get() bool {
77+
return atomic.LoadInt32((*int32)(ab)) == 1
78+
}
79+
6580
// TODO(mlaventure): move to runc package?
6681
func getLastRuntimeError(r *runc.Runc) (string, error) {
6782
if r.Log == "" {

0 commit comments

Comments
 (0)