Skip to content

Commit b9b4fa7

Browse files
authored
Merge pull request #4025 from thaJeztah/1.2_backport_fix_container_pid
[release/1.2 backport] Fix container pid race condition
2 parents 1f6ea50 + b970987 commit b9b4fa7

6 files changed

Lines changed: 54 additions & 20 deletions

File tree

container_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1528,3 +1528,52 @@ func TestContainerHook(t *testing.T) {
15281528
}
15291529
defer task.Delete(ctx, WithProcessKill)
15301530
}
1531+
1532+
func TestShortRunningTaskPid(t *testing.T) {
1533+
t.Parallel()
1534+
1535+
client, err := newClient(t, address)
1536+
if err != nil {
1537+
t.Fatal(err)
1538+
}
1539+
defer client.Close()
1540+
1541+
var (
1542+
image Image
1543+
ctx, cancel = testContext()
1544+
id = t.Name()
1545+
)
1546+
defer cancel()
1547+
1548+
image, err = client.GetImage(ctx, testImage)
1549+
if err != nil {
1550+
t.Fatal(err)
1551+
}
1552+
1553+
container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("true")))
1554+
if err != nil {
1555+
t.Fatal(err)
1556+
}
1557+
defer container.Delete(ctx, WithSnapshotCleanup)
1558+
1559+
task, err := container.NewTask(ctx, empty())
1560+
if err != nil {
1561+
t.Fatal(err)
1562+
}
1563+
defer task.Delete(ctx)
1564+
1565+
finishedC, err := task.Wait(ctx)
1566+
if err != nil {
1567+
t.Fatal(err)
1568+
}
1569+
1570+
if err := task.Start(ctx); err != nil {
1571+
t.Fatal(err)
1572+
}
1573+
1574+
int32PID := int32(task.Pid())
1575+
if int32PID <= 0 {
1576+
t.Errorf("Unexpected task pid %d", int32PID)
1577+
}
1578+
<-finishedC
1579+
}

runtime/v1/linux/proc/exec.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ func (e *execProcess) setExited(status int) {
9696
e.status = status
9797
e.exited = time.Now()
9898
e.parent.Platform.ShutdownConsole(context.Background(), e.console)
99-
e.pid.set(StoppedPID)
10099
close(e.waitBlock)
101100
}
102101

@@ -147,7 +146,7 @@ func (e *execProcess) kill(ctx context.Context, sig uint32, _ bool) error {
147146
switch {
148147
case pid == 0:
149148
return errors.Wrap(errdefs.ErrFailedPrecondition, "process not created")
150-
case pid < 0:
149+
case !e.exited.IsZero():
151150
return errors.Wrapf(errdefs.ErrNotFound, "process already finished")
152151
default:
153152
if err := unix.Kill(pid, syscall.Signal(sig)); err != nil {

runtime/v1/linux/proc/init.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ type Init struct {
6969
pausing *atomicBool
7070
status int
7171
exited time.Time
72-
pid safePid
72+
pid int
7373
closers []io.Closer
7474
stdin io.Closer
7575
stdio proc.Stdio
@@ -116,8 +116,6 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) error {
116116
err error
117117
socket *runc.Socket
118118
)
119-
p.pid.Lock()
120-
defer p.pid.Unlock()
121119

122120
if r.Terminal {
123121
if socket, err = runc.NewTempConsoleSocket(); err != nil {
@@ -197,7 +195,7 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) error {
197195
if err != nil {
198196
return errors.Wrap(err, "failed to retrieve OCI runtime container pid")
199197
}
200-
p.pid.pid = pid
198+
p.pid = pid
201199
return nil
202200
}
203201

@@ -213,7 +211,7 @@ func (p *Init) ID() string {
213211

214212
// Pid of the process
215213
func (p *Init) Pid() int {
216-
return p.pid.get()
214+
return p.pid
217215
}
218216

219217
// ExitStatus of the process
@@ -269,7 +267,6 @@ func (p *Init) setExited(status int) {
269267
p.exited = time.Now()
270268
p.status = status
271269
p.Platform.ShutdownConsole(context.Background(), p.console)
272-
p.pid.set(StoppedPID)
273270
close(p.waitBlock)
274271
}
275272

runtime/v1/linux/proc/init_state.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,6 @@ func (s *createdCheckpointState) Start(ctx context.Context) error {
161161
p := s.p
162162
sio := p.stdio
163163

164-
p.pid.Lock()
165-
defer p.pid.Unlock()
166-
167164
var (
168165
err error
169166
socket *runc.Socket
@@ -209,7 +206,7 @@ func (s *createdCheckpointState) Start(ctx context.Context) error {
209206
if err != nil {
210207
return errors.Wrap(err, "failed to retrieve OCI runtime container pid")
211208
}
212-
p.pid.pid = pid
209+
p.pid = pid
213210
return s.transition("running")
214211
}
215212

runtime/v1/linux/proc/process.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ import (
2525
// RuncRoot is the path to the root runc state directory
2626
const (
2727
RuncRoot = "/run/containerd/runc"
28-
// StoppedPID is the pid assigned after a container has run and stopped
29-
StoppedPID = -1
3028
)
3129

3230
func stateName(v interface{}) string {

runtime/v1/linux/proc/utils.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,6 @@ func (s *safePid) get() int {
4646
return s.pid
4747
}
4848

49-
func (s *safePid) set(pid int) {
50-
s.Lock()
51-
s.pid = pid
52-
s.Unlock()
53-
}
54-
5549
type atomicBool int32
5650

5751
func (ab *atomicBool) set(b bool) {

0 commit comments

Comments
 (0)