浏览代码

Merge pull request #36191 from cpuguy83/fix_attachable_network_race

Fix race in attachable network attachment
Yong Tang 7 年之前
父节点
当前提交
6987557e0c
共有 2 个文件被更改,包括 15 次插入5 次删除
  1. 11 4
      daemon/container_operations.go
  2. 4 1
      daemon/daemon.go

+ 11 - 4
daemon/container_operations.go

@@ -346,7 +346,9 @@ func (daemon *Daemon) updateNetwork(container *container.Container) error {
 }
 }
 
 
 func (daemon *Daemon) findAndAttachNetwork(container *container.Container, idOrName string, epConfig *networktypes.EndpointSettings) (libnetwork.Network, *networktypes.NetworkingConfig, error) {
 func (daemon *Daemon) findAndAttachNetwork(container *container.Container, idOrName string, epConfig *networktypes.EndpointSettings) (libnetwork.Network, *networktypes.NetworkingConfig, error) {
-	n, err := daemon.FindNetwork(getNetworkID(idOrName, epConfig))
+	id := getNetworkID(idOrName, epConfig)
+
+	n, err := daemon.FindNetwork(id)
 	if err != nil {
 	if err != nil {
 		// We should always be able to find the network for a
 		// We should always be able to find the network for a
 		// managed container.
 		// managed container.
@@ -379,21 +381,26 @@ func (daemon *Daemon) findAndAttachNetwork(container *container.Container, idOrN
 		retryCount int
 		retryCount int
 	)
 	)
 
 
+	if n == nil && daemon.attachableNetworkLock != nil {
+		daemon.attachableNetworkLock.Lock(id)
+		defer daemon.attachableNetworkLock.Unlock(id)
+	}
+
 	for {
 	for {
 		// In all other cases, attempt to attach to the network to
 		// In all other cases, attempt to attach to the network to
 		// trigger attachment in the swarm cluster manager.
 		// trigger attachment in the swarm cluster manager.
 		if daemon.clusterProvider != nil {
 		if daemon.clusterProvider != nil {
 			var err error
 			var err error
-			config, err = daemon.clusterProvider.AttachNetwork(getNetworkID(idOrName, epConfig), container.ID, addresses)
+			config, err = daemon.clusterProvider.AttachNetwork(id, container.ID, addresses)
 			if err != nil {
 			if err != nil {
 				return nil, nil, err
 				return nil, nil, err
 			}
 			}
 		}
 		}
 
 
-		n, err = daemon.FindNetwork(getNetworkID(idOrName, epConfig))
+		n, err = daemon.FindNetwork(id)
 		if err != nil {
 		if err != nil {
 			if daemon.clusterProvider != nil {
 			if daemon.clusterProvider != nil {
-				if err := daemon.clusterProvider.DetachNetwork(getNetworkID(idOrName, epConfig), container.ID); err != nil {
+				if err := daemon.clusterProvider.DetachNetwork(id, container.ID); err != nil {
 					logrus.Warnf("Could not rollback attachment for container %s to network %s: %v", container.ID, idOrName, err)
 					logrus.Warnf("Could not rollback attachment for container %s to network %s: %v", container.ID, idOrName, err)
 				}
 				}
 			}
 			}

+ 4 - 1
daemon/daemon.go

@@ -43,6 +43,7 @@ import (
 	"github.com/docker/docker/migrate/v1"
 	"github.com/docker/docker/migrate/v1"
 	"github.com/docker/docker/pkg/containerfs"
 	"github.com/docker/docker/pkg/containerfs"
 	"github.com/docker/docker/pkg/idtools"
 	"github.com/docker/docker/pkg/idtools"
+	"github.com/docker/docker/pkg/locker"
 	"github.com/docker/docker/pkg/plugingetter"
 	"github.com/docker/docker/pkg/plugingetter"
 	"github.com/docker/docker/pkg/sysinfo"
 	"github.com/docker/docker/pkg/sysinfo"
 	"github.com/docker/docker/pkg/system"
 	"github.com/docker/docker/pkg/system"
@@ -120,7 +121,8 @@ type Daemon struct {
 	hosts            map[string]bool // hosts stores the addresses the daemon is listening on
 	hosts            map[string]bool // hosts stores the addresses the daemon is listening on
 	startupDone      chan struct{}
 	startupDone      chan struct{}
 
 
-	attachmentStore network.AttachmentStore
+	attachmentStore       network.AttachmentStore
+	attachableNetworkLock *locker.Locker
 }
 }
 
 
 // StoreHosts stores the addresses the daemon is listening on
 // StoreHosts stores the addresses the daemon is listening on
@@ -564,6 +566,7 @@ func (daemon *Daemon) DaemonLeavesCluster() {
 func (daemon *Daemon) setClusterProvider(clusterProvider cluster.Provider) {
 func (daemon *Daemon) setClusterProvider(clusterProvider cluster.Provider) {
 	daemon.clusterProvider = clusterProvider
 	daemon.clusterProvider = clusterProvider
 	daemon.netController.SetClusterProvider(clusterProvider)
 	daemon.netController.SetClusterProvider(clusterProvider)
+	daemon.attachableNetworkLock = locker.New()
 }
 }
 
 
 // IsSwarmCompatible verifies if the current daemon
 // IsSwarmCompatible verifies if the current daemon