Skip to content

Commit e70b43f

Browse files
Don't create source directory whild the daemon is being shutdown
Signed-off-by: TomSweeneyRedHat <tsweeney@redhat.com>
1 parent 14156e6 commit e70b43f

6 files changed

Lines changed: 44 additions & 4 deletions

File tree

cmd/dockerd/daemon.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ func (cli *DaemonCli) start(opts daemonOptions) (err error) {
229229
api := apiserver.New(serverConfig)
230230
cli.api = api
231231

232+
var hosts []string
233+
232234
for i := 0; i < len(cli.Config.Hosts); i++ {
233235
var err error
234236
if cli.Config.Hosts[i], err = dopts.ParseHost(cli.Config.TLS, cli.Config.Hosts[i]); err != nil {
@@ -260,6 +262,7 @@ func (cli *DaemonCli) start(opts daemonOptions) (err error) {
260262
}
261263
}
262264
logrus.Debugf("Listener created for HTTP on %s (%s)", proto, addr)
265+
hosts = append(hosts, protoAddrParts[1])
263266
api.Accept(addr, ls...)
264267
}
265268

@@ -285,6 +288,8 @@ func (cli *DaemonCli) start(opts daemonOptions) (err error) {
285288
return fmt.Errorf("Error starting daemon: %v", err)
286289
}
287290

291+
d.StoreHosts(hosts)
292+
288293
if cli.Config.MetricsAddress != "" {
289294
if !d.HasExperimental() {
290295
return fmt.Errorf("metrics-addr is only supported when experimental is enabled")

daemon/daemon.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,18 @@ type Daemon struct {
109109

110110
seccompProfile []byte
111111
seccompProfilePath string
112+
113+
hosts map[string]bool // hosts stores the addresses the daemon is listening on
114+
}
115+
116+
// StoreHosts stores the addresses the daemon is listening on
117+
func (daemon *Daemon) StoreHosts(hosts []string) {
118+
if daemon.hosts == nil {
119+
daemon.hosts = make(map[string]bool)
120+
}
121+
for _, h := range hosts {
122+
daemon.hosts[h] = true
123+
}
112124
}
113125

114126
// HasExperimental returns whether the experimental features of the daemon are enabled or not

daemon/monitor.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ func (daemon *Daemon) StateChanged(id string, e libcontainerd.StateInfo) error {
3535
c.StreamConfig.Wait()
3636
c.Reset(false)
3737

38-
restart, wait, err := c.RestartManager().ShouldRestart(e.ExitCode, false, time.Since(c.StartedAt))
38+
// If daemon is being shutdown, don't let the container restart
39+
restart, wait, err := c.RestartManager().ShouldRestart(e.ExitCode, daemon.IsShuttingDown() || c.HasBeenManuallyStopped, time.Since(c.StartedAt))
3940
if err == nil && restart {
4041
c.RestartCount++
4142
c.SetRestarting(platformConstructExitStatus(e))

daemon/volumes_unix.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package daemon
66

77
import (
88
"encoding/json"
9+
"fmt"
910
"os"
1011
"path/filepath"
1112
"sort"
@@ -42,8 +43,19 @@ func (daemon *Daemon) setupMounts(c *container.Container) ([]container.Mount, er
4243
if err := daemon.lazyInitializeVolume(c.ID, m); err != nil {
4344
return nil, err
4445
}
46+
// If the daemon is being shutdown, we should not let a container start if it is trying to
47+
// mount the socket the daemon is listening on. During daemon shutdown, the socket
48+
// (/var/run/docker.sock by default) doesn't exist anymore causing the call to m.Setup to
49+
// create at directory instead. This in turn will prevent the daemon to restart.
50+
checkfunc := func(m *volume.MountPoint) error {
51+
if _, exist := daemon.hosts[m.Source]; exist && daemon.IsShuttingDown() {
52+
return fmt.Errorf("Could not mount %q to container while the daemon is shutting down", m.Source)
53+
}
54+
return nil
55+
}
56+
4557
rootUID, rootGID := daemon.GetRemappedUIDGID()
46-
path, err := m.Setup(c.MountLabel, rootUID, rootGID)
58+
path, err := m.Setup(c.MountLabel, rootUID, rootGID, checkfunc)
4759
if err != nil {
4860
return nil, err
4961
}

daemon/volumes_windows.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func (daemon *Daemon) setupMounts(c *container.Container) ([]container.Mount, er
2424
if err := daemon.lazyInitializeVolume(c.ID, mount); err != nil {
2525
return nil, err
2626
}
27-
s, err := mount.Setup(c.MountLabel, 0, 0)
27+
s, err := mount.Setup(c.MountLabel, 0, 0, nil)
2828
if err != nil {
2929
return nil, err
3030
}

volume/volume.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,9 @@ type MountPoint struct {
124124

125125
// Setup sets up a mount point by either mounting the volume if it is
126126
// configured, or creating the source directory if supplied.
127-
func (m *MountPoint) Setup(mountLabel string, rootUID, rootGID int) (path string, err error) {
127+
// The, optional, checkFun parameter allows doing additional checking
128+
// before creating the source directory on the host.
129+
func (m *MountPoint) Setup(mountLabel string, rootUID, rootGID int, checkFun func(m *MountPoint) error) (path string, err error) {
128130
defer func() {
129131
if err == nil {
130132
if label.RelabelNeeded(m.Mode) {
@@ -164,6 +166,14 @@ func (m *MountPoint) Setup(mountLabel string, rootUID, rootGID int) (path string
164166
}
165167
// system.MkdirAll() produces an error if m.Source exists and is a file (not a directory),
166168
if m.Type == mounttypes.TypeBind {
169+
// Before creating the source directory on the host, invoke checkFun if it's not nil. One of
170+
// the use case is to forbid creating the daemon socket as a directory if the daemon is in
171+
// the process of shutting down.
172+
if checkFun != nil {
173+
if err := checkFun(m); err != nil {
174+
return "", err
175+
}
176+
}
167177
// idtools.MkdirAllNewAs() produces an error if m.Source exists and is a file (not a directory)
168178
// also, makes sure that if the directory is created, the correct remapped rootUID/rootGID will own it
169179
if err := idtools.MkdirAllNewAs(m.Source, 0755, rootUID, rootGID); err != nil {

0 commit comments

Comments
 (0)