diff --git a/cmd/dockerd/daemon.go b/cmd/dockerd/daemon.go index 6277a7cf9eefa..1a324293b4c83 100644 --- a/cmd/dockerd/daemon.go +++ b/cmd/dockerd/daemon.go @@ -274,10 +274,21 @@ func (cli *DaemonCli) start(opts daemonOptions) (err error) { cli.TrustKeyPath = opts.common.TrustKey registryService := registry.NewService(cli.Config.ServiceOptions) - containerdRemote, err := libcontainerd.New(cli.getLibcontainerdRoot(), cli.getPlatformRemoteOptions()...) + + // libcontainerd.New add hook + hook := func() { + if cli.d == nil { + return + } + for _, c := range cli.d.List() { + c.CheckProcessIsRunning() + } + } + containerdRemote, err := libcontainerd.New(cli.getLibcontainerdRoot(), hook, cli.getPlatformRemoteOptions()...) if err != nil { return err } + signal.Trap(func() { cli.stop() <-stopc // wait for daemonCli.start() to return diff --git a/container/state.go b/container/state.go index 95fe05947e291..78bf2b4490b1c 100644 --- a/container/state.go +++ b/container/state.go @@ -8,6 +8,7 @@ import ( "golang.org/x/net/context" "github.com/docker/docker/api/types" + "github.com/docker/docker/utils" "github.com/docker/go-units" ) @@ -230,6 +231,17 @@ func (s *State) IsRunning() bool { return res } +// CheckProcessIsRunning check the the process of running container is still performed. +func (s *State) CheckProcessIsRunning() { + if !s.IsRunning() { + return + } + if !utils.IsProcessAlive(s.Pid) { + // TODO: force set exitcode:1, better to define new exitcode + s.SetStopped(&ExitStatus{ExitCode: 1}) + } +} + // GetPID holds the process id of a container. func (s *State) GetPID() int { s.Lock() diff --git a/libcontainerd/remote_unix.go b/libcontainerd/remote_unix.go index bc2daaf02a312..15e7de1af9cc8 100644 --- a/libcontainerd/remote_unix.go +++ b/libcontainerd/remote_unix.go @@ -61,10 +61,11 @@ type remote struct { oomScore int maxHealthCheckRetries int restoreFromTimestamp *timestamp.Timestamp + handleContainerdHook func() } // New creates a fresh instance of libcontainerd remote. -func New(stateDir string, options ...RemoteOption) (_ Remote, err error) { +func New(stateDir string, hook func(), options ...RemoteOption) (_ Remote, err error) { defer func() { if err != nil { err = fmt.Errorf("Failed to connect to containerd. Please make sure containerd is installed in your PATH or you have specified the correct address. Got error: %v", err) @@ -75,6 +76,7 @@ func New(stateDir string, options ...RemoteOption) (_ Remote, err error) { daemonPid: -1, eventTsPath: filepath.Join(stateDir, eventTimestampFilename), } + r.handleContainerdHook = hook for _, option := range options { if err := option.Apply(r); err != nil { return nil, err @@ -117,7 +119,6 @@ func New(stateDir string, options ...RemoteOption) (_ Remote, err error) { logrus.Errorf("libcontainerd: failed to convert timestamp: %q", err) } r.restoreFromTimestamp = tsp - go r.handleConnectionChange() if err := r.startEventsMonitor(); err != nil { @@ -179,6 +180,10 @@ func (r *remote) handleConnectionChange() { if err := r.runContainerdDaemon(); err != nil { //FIXME: Handle error logrus.Errorf("libcontainerd: error restarting containerd: %v", err) } + // Workaround to fix inconsistency stopped status + go func() { + r.handleContainerdHook() + }() continue } } diff --git a/libcontainerd/remote_windows.go b/libcontainerd/remote_windows.go index 74c10447bb1c8..6fb0d418dcb6b 100644 --- a/libcontainerd/remote_windows.go +++ b/libcontainerd/remote_windows.go @@ -26,7 +26,7 @@ func (r *remote) UpdateOptions(opts ...RemoteOption) error { // New creates a fresh instance of libcontainerd remote. On Windows, // this is not used as there is no remote containerd process. -func New(_ string, _ ...RemoteOption) (Remote, error) { +func New(_ string, _ func(), _ ...RemoteOption) (Remote, error) { return &remote{}, nil }