Browse Source

Ignore SIGPIPE events, resolves #19728

Using golang 1.6, is it now possible to ignore SIGPIPE events on
stdout/stderr.  Previous versions of the golang library cached 10
events and then killed the process receiving the events.

systemd-journald sends SIGPIPE events when jounald is restarted and
the target of the unit file writes to stdout/stderr. Docker logs to stdout/stderr.

This patch silently ignores all SIGPIPE events.

Signed-off-by: Jhon Honce <jhonce@redhat.com>
Jhon Honce 9 years ago
parent
commit
55a367d2fe
2 changed files with 14 additions and 7 deletions
  1. 5 5
      cmd/dockerd/daemon.go
  2. 9 2
      pkg/signal/trap.go

+ 5 - 5
cmd/dockerd/daemon.go

@@ -127,6 +127,11 @@ func (cli *DaemonCli) start() (err error) {
 	stopc := make(chan bool)
 	stopc := make(chan bool)
 	defer close(stopc)
 	defer close(stopc)
 
 
+	signal.Trap(func() {
+		cli.stop()
+		<-stopc // wait for daemonCli.start() to return
+	})
+
 	// warn from uuid package when running the daemon
 	// warn from uuid package when running the daemon
 	uuid.Loggerf = logrus.Warnf
 	uuid.Loggerf = logrus.Warnf
 
 
@@ -280,11 +285,6 @@ func (cli *DaemonCli) start() (err error) {
 	serveAPIWait := make(chan error)
 	serveAPIWait := make(chan error)
 	go api.Wait(serveAPIWait)
 	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
 	// after the daemon is done setting up we can notify systemd api
 	notifySystem()
 	notifySystem()
 
 

+ 9 - 2
pkg/signal/trap.go

@@ -18,15 +18,22 @@ import (
 // * If SIGINT or SIGTERM are received 3 times before cleanup is complete, then cleanup is
 // * 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)
 //   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.
 // * 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()) {
 func Trap(cleanup func()) {
 	c := make(chan os.Signal, 1)
 	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...)
 	gosignal.Notify(c, signals...)
 	go func() {
 	go func() {
 		interruptCount := uint32(0)
 		interruptCount := uint32(0)
 		for sig := range c {
 		for sig := range c {
+			if sig == syscall.SIGPIPE {
+				continue
+			}
+
 			go func(sig os.Signal) {
 			go func(sig os.Signal) {
 				logrus.Infof("Processing signal '%v'", sig)
 				logrus.Infof("Processing signal '%v'", sig)
 				switch sig {
 				switch sig {