diff --git a/daemon/daemon.go b/daemon/daemon.go index 4b78d01370..c9ffb405f8 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -116,6 +116,7 @@ type Daemon struct { diskUsageRunning int32 pruneRunning int32 hosts map[string]bool // hosts stores the addresses the daemon is listening on + startupDone chan struct{} } // StoreHosts stores the addresses the daemon is listening on @@ -543,7 +544,10 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe } os.Setenv("TMPDIR", realTmp) - d := &Daemon{configStore: config} + d := &Daemon{ + configStore: config, + startupDone: make(chan struct{}), + } // Ensure the daemon is properly shutdown if there is a failure during // initialization defer func() { @@ -740,6 +744,7 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe if err := d.restore(); err != nil { return nil, err } + close(d.startupDone) // FIXME: this method never returns an error info, _ := d.SystemInfo() @@ -760,6 +765,10 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe return d, nil } +func (daemon *Daemon) waitForStartupDone() { + <-daemon.startupDone +} + func (daemon *Daemon) shutdownContainer(c *container.Container) error { stopTimeout := c.StopTimeout() // TODO(windows): Handle docker restart with paused containers diff --git a/daemon/monitor.go b/daemon/monitor.go index 5bf9d945d1..006db3db21 100644 --- a/daemon/monitor.go +++ b/daemon/monitor.go @@ -69,6 +69,10 @@ func (daemon *Daemon) StateChanged(id string, e libcontainerd.StateInfo) error { go func() { err := <-wait if err == nil { + // daemon.netController is initialized when daemon is restoring containers. + // But containerStart will use daemon.netController segment. + // So to avoid panic at startup process, here must wait util daemon restore done. + daemon.waitForStartupDone() if err = daemon.containerStart(c, "", "", false); err != nil { logrus.Debugf("failed to restart container: %+v", err) }