1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Relax global client lock on containerd restore.

This unblocks the client to take other restore requests and makes sure
that a long/stuck request can't block the client forever.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
Brian Goff 2018-04-10 11:05:11 -04:00
parent ea579a6194
commit 806700e410

View file

@ -34,7 +34,7 @@ import (
"github.com/docker/docker/errdefs"
"github.com/docker/docker/pkg/ioutils"
"github.com/opencontainers/image-spec/specs-go/v1"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@ -131,9 +131,30 @@ func (c *client) Version(ctx context.Context) (containerd.Version, error) {
return c.getRemote().Version(ctx)
}
// Restore loads the containerd container.
// It should not be called concurrently with any other operation for the given ID.
func (c *client) Restore(ctx context.Context, id string, attachStdio StdioCallback) (alive bool, pid int, err error) {
c.Lock()
defer c.Unlock()
_, ok := c.containers[id]
if ok {
c.Unlock()
return false, 0, errors.WithStack(newConflictError("id already in use"))
}
cntr := &container{}
c.containers[id] = cntr
cntr.mu.Lock()
defer cntr.mu.Unlock()
c.Unlock()
defer func() {
if err != nil {
c.Lock()
delete(c.containers, id)
c.Unlock()
}
}()
var dio *cio.DirectIO
defer func() {
@ -144,9 +165,9 @@ func (c *client) Restore(ctx context.Context, id string, attachStdio StdioCallba
err = wrapError(err)
}()
ctr, err := c.remote.LoadContainer(ctx, id)
ctr, err := c.getRemote().LoadContainer(ctx, id)
if err != nil {
return false, -1, errors.WithStack(err)
return false, -1, errors.WithStack(wrapError(err))
}
attachIO := func(fifos *cio.FIFOSet) (cio.IO, error) {
@ -160,24 +181,23 @@ func (c *client) Restore(ctx context.Context, id string, attachStdio StdioCallba
}
t, err := ctr.Task(ctx, attachIO)
if err != nil && !containerderrors.IsNotFound(err) {
return false, -1, err
return false, -1, errors.Wrap(wrapError(err), "error getting containerd task for container")
}
if t != nil {
s, err := t.Status(ctx)
if err != nil {
return false, -1, err
return false, -1, errors.Wrap(wrapError(err), "error getting task status")
}
alive = s.Status != containerd.Stopped
pid = int(t.Pid())
}
c.containers[id] = &container{
bundleDir: filepath.Join(c.stateDir, id),
ctr: ctr,
task: t,
// TODO(mlaventure): load execs
}
cntr.bundleDir = filepath.Join(c.stateDir, id)
cntr.ctr = ctr
cntr.task = t
// TODO(mlaventure): load execs
c.logger.WithFields(logrus.Fields{
"container": id,