X Tutup
Skip to content

Commit b4cc42d

Browse files
authored
Merge pull request containerd#1460 from mlaventure/pid-host-kill-init
Ensure all init children are dead when it exits
2 parents d3e1132 + 939ad32 commit b4cc42d

File tree

7 files changed

+132
-54
lines changed

7 files changed

+132
-54
lines changed

container_linux_test.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,3 +896,79 @@ func TestContainerRuntimeOptions(t *testing.T) {
896896
t.Errorf("task creation should have failed because of lack of executable. Instead failed with: %v", err.Error())
897897
}
898898
}
899+
900+
func TestContainerKillInitPidHost(t *testing.T) {
901+
client, err := newClient(t, address)
902+
if err != nil {
903+
t.Fatal(err)
904+
}
905+
defer client.Close()
906+
907+
var (
908+
image Image
909+
ctx, cancel = testContext()
910+
id = t.Name()
911+
)
912+
defer cancel()
913+
914+
image, err = client.GetImage(ctx, testImage)
915+
if err != nil {
916+
t.Error(err)
917+
return
918+
}
919+
920+
container, err := client.NewContainer(ctx, id,
921+
withNewSnapshot(id, image),
922+
WithNewSpec(withImageConfig(image),
923+
withProcessArgs("sh", "-c", "sleep 42; echo hi"),
924+
WithHostNamespace(specs.PIDNamespace),
925+
),
926+
)
927+
if err != nil {
928+
t.Error(err)
929+
return
930+
}
931+
defer container.Delete(ctx, WithSnapshotCleanup)
932+
933+
stdout := bytes.NewBuffer(nil)
934+
task, err := container.NewTask(ctx, NewIO(bytes.NewBuffer(nil), stdout, bytes.NewBuffer(nil)))
935+
if err != nil {
936+
t.Error(err)
937+
return
938+
}
939+
defer task.Delete(ctx)
940+
941+
statusC, err := task.Wait(ctx)
942+
if err != nil {
943+
t.Error(err)
944+
return
945+
}
946+
947+
if err := task.Start(ctx); err != nil {
948+
t.Error(err)
949+
return
950+
}
951+
952+
if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
953+
t.Error(err)
954+
}
955+
956+
// Give the shim time to reap the init process and kill the orphans
957+
select {
958+
case <-statusC:
959+
case <-time.After(100 * time.Millisecond):
960+
}
961+
962+
b, err := exec.Command("ps", "ax").CombinedOutput()
963+
if err != nil {
964+
t.Fatal(err)
965+
}
966+
967+
if strings.Contains(string(b), "sleep 42") {
968+
t.Fatalf("killing init didn't kill all its children:\n%v", string(b))
969+
}
970+
971+
if _, err := task.Delete(ctx, WithProcessKill); err != nil {
972+
t.Error(err)
973+
}
974+
}

linux/runtime.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,10 @@ func (r *Runtime) loadTasks(ctx context.Context, ns string) ([]*Task, error) {
367367
func (r *Runtime) cleanupAfterDeadShim(ctx context.Context, bundle *bundle, ns, id string, pid int, ec chan runc.Exit) error {
368368
ctx = namespaces.WithNamespace(ctx, ns)
369369
if err := r.terminate(ctx, bundle, ns, id); err != nil {
370-
return errors.New("failed to terminate task, leaving bundle for debugging")
370+
if r.config.ShimDebug {
371+
return errors.Wrap(err, "failed to terminate task, leaving bundle for debugging")
372+
}
373+
log.G(ctx).WithError(err).Warn("failed to terminate task")
371374
}
372375

373376
if ec != nil {

linux/shim/service.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,14 @@ func (s *Service) checkProcesses(e runc.Exit) {
393393
defer s.mu.Unlock()
394394
for _, p := range s.processes {
395395
if p.Pid() == e.Pid {
396+
if ip, ok := p.(*initProcess); ok {
397+
// Ensure all children are killed
398+
if err := ip.killAll(s.context); err != nil {
399+
log.G(s.context).WithError(err).WithField("id", ip.ID()).
400+
Error("failed to kill init's children")
401+
}
402+
}
403+
396404
p.SetExited(e.Status)
397405
s.events <- &eventsapi.TaskExit{
398406
ContainerID: s.id,

reaper/reaper.go

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
package reaper
44

55
import (
6-
"bytes"
76
"os/exec"
87
"sync"
98
"time"
@@ -47,23 +46,6 @@ type Monitor struct {
4746
subscribers map[chan runc.Exit]struct{}
4847
}
4948

50-
func (m *Monitor) Output(c *exec.Cmd) ([]byte, error) {
51-
var b bytes.Buffer
52-
c.Stdout = &b
53-
if err := m.Run(c); err != nil {
54-
return nil, err
55-
}
56-
return b.Bytes(), nil
57-
}
58-
59-
func (m *Monitor) CombinedOutput(c *exec.Cmd) ([]byte, error) {
60-
var b bytes.Buffer
61-
c.Stdout = &b
62-
c.Stderr = &b
63-
err := m.Run(c)
64-
return b.Bytes(), err
65-
}
66-
6749
// Start starts the command a registers the process with the reaper
6850
func (m *Monitor) Start(c *exec.Cmd) (chan runc.Exit, error) {
6951
ec := m.Subscribe()
@@ -74,16 +56,9 @@ func (m *Monitor) Start(c *exec.Cmd) (chan runc.Exit, error) {
7456
return ec, nil
7557
}
7658

77-
// Run runs and waits for the command to finish
78-
func (m *Monitor) Run(c *exec.Cmd) error {
79-
ec, err := m.Start(c)
80-
if err != nil {
81-
return err
82-
}
83-
_, err = m.Wait(c, ec)
84-
return err
85-
}
86-
59+
// Wait blocks until a process is signal as dead.
60+
// User should rely on the value of the exit status to determine if the
61+
// command was successful or not.
8762
func (m *Monitor) Wait(c *exec.Cmd, ec chan runc.Exit) (int, error) {
8863
for e := range ec {
8964
if e.Pid == c.Process.Pid {

vendor.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
github.com/coreos/go-systemd 48702e0da86bd25e76cfef347e2adeb434a0d0a6
2-
github.com/containerd/go-runc e103f453ff3db23ec69d31371cadc1ea0ce87ec0
2+
github.com/containerd/go-runc ba22f6a82e52be3be4eb4a00000fe816f4b41c2e
33
github.com/containerd/console 76d18fd1d66972718ab2284449591db0b3cdb4de
44
github.com/containerd/cgroups e6d1aa8c71c6103624b2c6e6f4be0863b67027f1
55
github.com/docker/go-metrics 8fd5772bf1584597834c6f7961a530f06cbfbb87

vendor/github.com/containerd/go-runc/monitor.go

Lines changed: 0 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/containerd/go-runc/runc.go

Lines changed: 40 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
X Tutup