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

Fix race condition between container register and mount

When a container is created it is registered before the mount is created. This can lead to mount does not exist errors when inspecting between create and mount.

Fixes #18753

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
This commit is contained in:
Derek McGowan 2015-12-21 11:23:20 -08:00
parent d04fa49a0d
commit d8e090669e
3 changed files with 37 additions and 30 deletions

View file

@ -74,6 +74,15 @@ func (daemon *Daemon) create(params types.ContainerCreateConfig) (*container.Con
}
}()
if err := daemon.setSecurityOptions(container, params.HostConfig); err != nil {
return nil, err
}
// Set RWLayer for container after mount labels have been set
if err := daemon.setRWLayer(container); err != nil {
return nil, err
}
if err := daemon.Register(container); err != nil {
return nil, err
}
@ -96,11 +105,6 @@ func (daemon *Daemon) create(params types.ContainerCreateConfig) (*container.Con
}
}()
// Set RWLayer for container after mount labels have been set
if err := daemon.setRWLayer(container); err != nil {
return nil, err
}
if err := daemon.createContainerPlatformSpecificSettings(container, params.Config, params.HostConfig, img); err != nil {
return nil, err
}

View file

@ -226,18 +226,30 @@ func (daemon *Daemon) load(id string) (*container.Container, error) {
return container, nil
}
// Register makes a container object usable by the daemon as <container.ID>
func (daemon *Daemon) Register(container *container.Container) error {
func (daemon *Daemon) registerName(container *container.Container) error {
if daemon.Exists(container.ID) {
return fmt.Errorf("Container is already loaded")
}
if err := validateID(container.ID); err != nil {
return err
}
if err := daemon.ensureName(container); err != nil {
return err
if container.Name == "" {
name, err := daemon.generateNewName(container.ID)
if err != nil {
return err
}
container.Name = name
if err := container.ToDiskLocking(); err != nil {
logrus.Errorf("Error saving container name to disk: %v", err)
}
}
return nil
}
// Register makes a container object usable by the daemon as <container.ID>
func (daemon *Daemon) Register(container *container.Container) error {
// Attach to stdout and stderr
if container.Config.OpenStdin {
container.NewInputPipes()
@ -277,21 +289,6 @@ func (daemon *Daemon) Register(container *container.Container) error {
return nil
}
func (daemon *Daemon) ensureName(container *container.Container) error {
if container.Name == "" {
name, err := daemon.generateNewName(container.ID)
if err != nil {
return err
}
container.Name = name
if err := container.ToDiskLocking(); err != nil {
logrus.Errorf("Error saving container name to disk: %v", err)
}
}
return nil
}
func (daemon *Daemon) restore() error {
type cr struct {
container *container.Container
@ -368,6 +365,10 @@ func (daemon *Daemon) restore() error {
logrus.Debugf("Setting default id - %s", err)
}
}
if err := daemon.registerName(container); err != nil {
logrus.Errorf("Failed to register container %s: %s", container.ID, err)
return
}
if err := daemon.Register(container); err != nil {
logrus.Errorf("Failed to register container %s: %s", container.ID, err)
@ -1392,14 +1393,13 @@ func tempDir(rootDir string, rootUID, rootGID int) (string, error) {
return tmpDir, idtools.MkdirAllAs(tmpDir, 0700, rootUID, rootGID)
}
func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig *containertypes.HostConfig) error {
func (daemon *Daemon) setSecurityOptions(container *container.Container, hostConfig *containertypes.HostConfig) error {
container.Lock()
if err := parseSecurityOpt(container, hostConfig); err != nil {
container.Unlock()
return err
}
container.Unlock()
defer container.Unlock()
return parseSecurityOpt(container, hostConfig)
}
func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig *containertypes.HostConfig) error {
// Do not lock while creating volumes since this could be calling out to external plugins
// Don't want to block other actions, like `docker ps` because we're waiting on an external plugin
if err := daemon.registerMountPoints(container, hostConfig); err != nil {

View file

@ -31,6 +31,9 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos
// creating a container, not during start.
if hostConfig != nil {
logrus.Warn("DEPRECATED: Setting host configuration options when the container starts is deprecated and will be removed in Docker 1.12")
if err := daemon.setSecurityOptions(container, hostConfig); err != nil {
return err
}
if err := daemon.setHostConfig(container, hostConfig); err != nil {
return err
}