Skip to content
This repository has been archived by the owner on Mar 31, 2023. It is now read-only.

Commit

Permalink
Merge pull request #16 from cybozu-go/sighup2
Browse files Browse the repository at this point in the history
Fix SIGPIPE handling, take 2.
  • Loading branch information
nojima authored Apr 26, 2017
2 parents 21e6f59 + 8c034e8 commit 86706dc
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 8 deletions.
2 changes: 1 addition & 1 deletion default.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ var (
func init() {
defaultEnv = NewEnvironment(context.Background())
handleSignal(defaultEnv)
ignoreSigPipe()
handleSigPipe()
}

// Stop just declares no further Go will be called.
Expand Down
43 changes: 37 additions & 6 deletions sigpipe.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,43 @@ import (
"syscall"
)

func ignoreSigPipe() {
// signal.Ignore does NOT ignore signals; instead, it just stop
// relaying signals to the channel.
//signal.Ignore(syscall.SIGPIPE)
const (
sigPipeExit = 2
)

// unbuffered channel will effectively ignore the signal
c := make(chan os.Signal)
// handleSigPipe catches SIGPIPE and exit abnormally with status code 2.
//
// Background:
//
// systemd interprets programs exited with SIGPIPE as
// "successfully exited" because its default SuccessExitStatus=
// includes SIGPIPE.
// https://www.freedesktop.org/software/systemd/man/systemd.service.html
//
// Normal Go programs ignore SIGPIPE for file descriptors other than
// stdout(1) and stderr(2). If SIGPIPE is raised from stdout or stderr,
// Go programs exit with a SIGPIPE signal.
// https://golang.org/pkg/os/signal/#hdr-SIGPIPE
//
// journald is a service tightly integrated in systemd. Go programs
// running as a systemd service will normally connect its stdout and
// stderr pipes to journald. Unfortunately though, journald often
// dies and restarts due to bugs, and once it restarts, programs
// whose stdout and stderr was connected to journald will receive
// SIGPIPE at their next writes to stdout or stderr.
//
// Combined these specifications and problems all together, Go programs
// running as systemd services often die with SIGPIPE, but systemd will
// not restarts them as they "successfully exited" except when the service
// is configured with SuccessExitStatus= without SIGPIPE or Restart=always.
//
// Handling SIGPIPE manually and exiting with abnormal status code 2
// can work around the problem.
func handleSigPipe() {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGPIPE)
go func() {
<-c
os.Exit(sigPipeExit)
}()
}
2 changes: 1 addition & 1 deletion sigpipe_windows.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package cmd

func ignoreSigPipe() {}
func handleSigPipe() {}

0 comments on commit 86706dc

Please sign in to comment.