Repository: moby/moby
File: daemon/daemon.go (Go)

Code before:
		group.Add(1)
		go func(c *container.Container) {
			_ = sem.Acquire(context.Background(), 1)

			if err := daemon.registerLinks(c, c.HostConfig); err != nil {
				log.G(context.TODO()).WithField("container", c.ID).WithError(err).Error("failed to register link for container")
			}

			sem.Release(1)
			group.Done()
		}(c)
	}
	group.Wait()

	for c, notifyChan := range restartContainers {
		group.Add(1)
		go func(c *container.Container, chNotify chan struct{}) {
			_ = sem.Acquire(context.Background(), 1)

			logger := log.G(context.TODO()).WithField("container", c.ID)

			logger.Debug("starting container")

			// ignore errors here as this is a best effort to wait for children
			// (legacy links or container network) to be running before we try to start the container
			if children := dependentContainers[c]; len(children) > 0 {
				timeout := time.NewTimer(5 * time.Second)
				defer timeout.Stop()

				for _, child := range children {
					if notifier, exists := restartContainers[child]; exists {
						select {
						case <-notifier:
						case <-timeout.C:
						}
					}
				}
			}

			if err := daemon.prepareMountPoints(c); err != nil {
				logger.WithError(err).Error("failed to prepare mount points for container")
			}
			if err := daemon.containerStart(context.Background(), cfg, c, "", "", true); err != nil {
				logger.WithError(err).Error("failed to start container")
			}
			close(chNotify)

			sem.Release(1)
			group.Done()
		}(c, notifyChan)
	}

Review comment (suggestion):
Accumulating the dependent containers into a map doesn't really afford us anything, at the cost of some memory.
```suggestion
			if children := daemon.GetDependentContainers(c); len(children) > 0 {
```

Code after:
			_ = sem.Acquire(context.Background(), 1)

			if err := daemon.registerLinks(c, c.HostConfig); err != nil {
				log.G(context.TODO()).WithField("container", c.ID).WithError(err).Error("failed to register link for container")
			}

			sem.Release(1)
			group.Done()
		}(c)
	}
	group.Wait()

	for c, notifyChan := range restartContainers {
		group.Add(1)
		go func(c *container.Container, chNotify chan struct{}) {
			_ = sem.Acquire(context.Background(), 1)

			logger := log.G(context.TODO()).WithField("container", c.ID)

			logger.Debug("starting container")

			// ignore errors here as this is a best effort to wait for children
			// (legacy links or container network) to be running before we try to start the container
			if children := daemon.GetDependentContainers(c); len(children) > 0 {
				timeout := time.NewTimer(5 * time.Second)
				defer timeout.Stop()

				for _, child := range children {
					if notifier, exists := restartContainers[child]; exists {
						select {
						case <-notifier:
						case <-timeout.C:
						}
					}
				}
			}

			if err := daemon.prepareMountPoints(c); err != nil {
				logger.WithError(err).Error("failed to prepare mount points for container")
			}
			if err := daemon.containerStart(context.Background(), cfg, c, "", "", true); err != nil {
				logger.WithError(err).Error("failed to start container")
			}
			close(chNotify)

			sem.Release(1)
			group.Done()
		}(c, notifyChan)
	}
	group.Wait()