diff options
author | Brian Goff <cpuguy83@gmail.com> | 2018-04-20 10:48:54 -0400 |
---|---|---|
committer | Kir Kolyshkin <kolyshkin@gmail.com> | 2018-06-07 17:27:02 -0700 |
commit | dbeb4329655e91dbe0e6574405937f03fabf3f2f (patch) | |
tree | 1726dd63bea30903ac8900eeff6645cea9173331 /plugin/executor | |
parent | d47c45175b13e97475649dfe8b1ab1034c4865d0 (diff) | |
download | docker-dbeb4329655e91dbe0e6574405937f03fabf3f2f.tar.gz |
Fix panic on daemon restart with running plugin
Scenario:
Daemon is ungracefully shutdown and leaves plugins running (no
live-restore).
Daemon comes back up.
The next time a container tries to use that plugin it will cause a
daemon panic because the plugin client is not set.
This fixes that by ensuring that the plugin does get shutdown.
Note, I do not think there would be any harm in just re-attaching to the
running plugin instead of shutting it down, however historically we shut
down plugins and containers when live-restore is not enabled.
[kir@: consolidate code to deleteTaskAndContainer, a few minor nits]
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Diffstat (limited to 'plugin/executor')
-rw-r--r-- | plugin/executor/containerd/containerd.go | 45 |
1 files changed, 19 insertions, 26 deletions
diff --git a/plugin/executor/containerd/containerd.go b/plugin/executor/containerd/containerd.go index e490ef0a9e..e0267582ec 100644 --- a/plugin/executor/containerd/containerd.go +++ b/plugin/executor/containerd/containerd.go @@ -58,6 +58,19 @@ type Executor struct { exitHandler ExitHandler } +// deleteTaskAndContainer deletes plugin task and then plugin container from containerd +func deleteTaskAndContainer(ctx context.Context, cli Client, id string) { + _, _, err := cli.DeleteTask(ctx, id) + if err != nil && !errdefs.IsNotFound(err) { + logrus.WithError(err).WithField("id", id).Error("failed to delete plugin task from containerd") + } + + err = cli.Delete(ctx, id) + if err != nil && !errdefs.IsNotFound(err) { + logrus.WithError(err).WithField("id", id).Error("failed to delete plugin container from containerd") + } +} + // Create creates a new container func (e *Executor) Create(id string, spec specs.Spec, stdout, stderr io.WriteCloser) error { opts := runctypes.RuncOptions{ @@ -87,34 +100,21 @@ func (e *Executor) Create(id string, spec specs.Spec, stdout, stderr io.WriteClo _, err = e.client.Start(ctx, id, "", false, attachStreamsFunc(stdout, stderr)) if err != nil { - if _, _, err2 := e.client.DeleteTask(ctx, id); err2 != nil && !errdefs.IsNotFound(err2) { - logrus.WithError(err2).WithField("id", id).Warn("Received an error while attempting to clean up containerd plugin task after failed start") - } - if err2 := e.client.Delete(ctx, id); err2 != nil && !errdefs.IsNotFound(err2) { - logrus.WithError(err2).WithField("id", id).Warn("Received an error while attempting to clean up containerd plugin container after failed start") - } + deleteTaskAndContainer(ctx, e.client, id) } return err } // Restore restores a container -func (e *Executor) Restore(id string, stdout, stderr io.WriteCloser) error { +func (e *Executor) Restore(id string, stdout, stderr io.WriteCloser) (bool, error) { alive, _, err := e.client.Restore(context.Background(), id, attachStreamsFunc(stdout, stderr)) if err != nil && !errdefs.IsNotFound(err) { - return err + return false, err } if !alive { - _, _, err = e.client.DeleteTask(context.Background(), id) - if err != nil && !errdefs.IsNotFound(err) { - logrus.WithError(err).Errorf("failed to delete container plugin %s task from containerd", id) - } - - err = e.client.Delete(context.Background(), id) - if err != nil && !errdefs.IsNotFound(err) { - logrus.WithError(err).Errorf("failed to delete container plugin %s from containerd", id) - } + deleteTaskAndContainer(context.Background(), e.client, id) } - return nil + return alive, nil } // IsRunning returns if the container with the given id is running @@ -133,14 +133,7 @@ func (e *Executor) Signal(id string, signal int) error { func (e *Executor) ProcessEvent(id string, et libcontainerd.EventType, ei libcontainerd.EventInfo) error { switch et { case libcontainerd.EventExit: - // delete task and container - if _, _, err := e.client.DeleteTask(context.Background(), id); err != nil { - logrus.WithError(err).Errorf("failed to delete container plugin %s task from containerd", id) - } - - if err := e.client.Delete(context.Background(), id); err != nil { - logrus.WithError(err).Errorf("failed to delete container plugin %s from containerd", id) - } + deleteTaskAndContainer(context.Background(), e.client, id) return e.exitHandler.HandleExitEvent(ei.ContainerID) } return nil |