Browse code

Move call to Daemon.registerLinks out of Daemon.setHostConfig

The call from Daemon.create -> Daemon.setHostConfig acquired
container.Lock, but didn't need to because the container is
newly created and solely owned by the caller. The call from
Daemon.restore did not acquire the lock.

Signed-off-by: Rob Murray <rob.murray@docker.com>

Rob Murray authored on 2025/11/14 20:27:52
Showing 5 changed files
... ...
@@ -221,11 +221,6 @@ func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig *
221 221
 	container.Lock()
222 222
 	defer container.Unlock()
223 223
 
224
-	// Register any links from the host config before starting the container
225
-	if err := daemon.registerLinks(container, hostConfig); err != nil {
226
-		return err
227
-	}
228
-
229 224
 	if hostConfig != nil && hostConfig.NetworkMode == "" {
230 225
 		hostConfig.NetworkMode = networktypes.NetworkDefault
231 226
 	}
... ...
@@ -247,7 +247,9 @@ func (daemon *Daemon) create(ctx context.Context, daemonCfg *config.Config, opts
247 247
 	if err := daemon.setHostConfig(ctr, opts.params.HostConfig, opts.params.DefaultReadOnlyNonRecursive); err != nil {
248 248
 		return nil, err
249 249
 	}
250
-
250
+	if err := daemon.registerLinks(ctr); err != nil {
251
+		return nil, err
252
+	}
251 253
 	if err := daemon.createContainerOSSpecificSettings(ctx, ctr, opts.params.Config, opts.params.HostConfig); err != nil {
252 254
 		return nil, err
253 255
 	}
... ...
@@ -592,7 +592,7 @@ func (daemon *Daemon) restore(ctx context.Context, cfg *configStore, containers
592 592
 		go func(c *container.Container) {
593 593
 			_ = sem.Acquire(context.Background(), 1)
594 594
 
595
-			if err := daemon.registerLinks(c, c.HostConfig); err != nil {
595
+			if err := daemon.registerLinks(c); err != nil {
596 596
 				log.G(ctx).WithField("container", c.ID).WithError(err).Error("failed to register link for container")
597 597
 			}
598 598
 
... ...
@@ -1504,12 +1504,12 @@ func getUnmountOnShutdownPath(config *config.Config) string {
1504 1504
 
1505 1505
 // registerLinks registers network links between container and other containers
1506 1506
 // with the daemon using the specification in hostConfig.
1507
-func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *containertypes.HostConfig) error {
1508
-	if hostConfig == nil || hostConfig.NetworkMode.IsUserDefined() {
1507
+func (daemon *Daemon) registerLinks(ctr *container.Container) error {
1508
+	if ctr.HostConfig == nil || ctr.HostConfig.NetworkMode.IsUserDefined() {
1509 1509
 		return nil
1510 1510
 	}
1511 1511
 
1512
-	for _, l := range hostConfig.Links {
1512
+	for _, l := range ctr.HostConfig.Links {
1513 1513
 		name, alias, err := opts.ParseLink(l)
1514 1514
 		if err != nil {
1515 1515
 			return err
... ...
@@ -1542,7 +1542,7 @@ func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *
1542 1542
 		if child.HostConfig.NetworkMode.IsHost() {
1543 1543
 			return cerrdefs.ErrInvalidArgument.WithMessage("conflicting options: host type networking can't be used with links. This would result in undefined behavior")
1544 1544
 		}
1545
-		if err := daemon.registerLink(container, child, alias); err != nil {
1545
+		if err := daemon.registerLink(ctr, child, alias); err != nil {
1546 1546
 			return err
1547 1547
 		}
1548 1548
 	}
... ...
@@ -464,7 +464,7 @@ func initBridgeDriver(controller *libnetwork.Controller, config config.BridgeCon
464 464
 
465 465
 // registerLinks sets up links between containers and writes the
466 466
 // configuration out for persistence. As of Windows TP4, links are not supported.
467
-func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *containertypes.HostConfig) error {
467
+func (daemon *Daemon) registerLinks(container *container.Container) error {
468 468
 	return nil
469 469
 }
470 470