diff --git a/cmd/dockerd/daemon.go b/cmd/dockerd/daemon.go index 3df9400a98..cdbdefc418 100644 --- a/cmd/dockerd/daemon.go +++ b/cmd/dockerd/daemon.go @@ -127,6 +127,11 @@ func (cli *DaemonCli) start() (err error) { stopc := make(chan bool) defer close(stopc) + signal.Trap(func() { + cli.stop() + <-stopc // wait for daemonCli.start() to return + }) + // warn from uuid package when running the daemon uuid.Loggerf = logrus.Warnf @@ -280,11 +285,6 @@ func (cli *DaemonCli) start() (err error) { serveAPIWait := make(chan error) go api.Wait(serveAPIWait) - signal.Trap(func() { - cli.stop() - <-stopc // wait for daemonCli.start() to return - }) - // after the daemon is done setting up we can notify systemd api notifySystem() diff --git a/pkg/signal/trap.go b/pkg/signal/trap.go index 2cf5ccf0d2..874509e714 100644 --- a/pkg/signal/trap.go +++ b/pkg/signal/trap.go @@ -18,15 +18,22 @@ import ( // * If SIGINT or SIGTERM are received 3 times before cleanup is complete, then cleanup is // skipped and the process is terminated immediately (allows force quit of stuck daemon) // * A SIGQUIT always causes an exit without cleanup, with a goroutine dump preceding exit. +// * Ignore SIGPIPE events. These are generated by systemd when journald is restarted while +// the docker daemon is not restarted and also running under systemd. +// Fixes https://github.com/docker/docker/issues/19728 // func Trap(cleanup func()) { c := make(chan os.Signal, 1) - // we will handle INT, TERM, QUIT here - signals := []os.Signal{os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT} + // we will handle INT, TERM, QUIT, SIGPIPE here + signals := []os.Signal{os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGPIPE} gosignal.Notify(c, signals...) go func() { interruptCount := uint32(0) for sig := range c { + if sig == syscall.SIGPIPE { + continue + } + go func(sig os.Signal) { logrus.Infof("Processing signal '%v'", sig) switch sig {