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

Fix SIGPIPE handling, take 2. #16

Merged
merged 1 commit into from
Apr 26, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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() {}