Skip to content
Advertisement

Getting a pipe status in Go

I’m unable to get a pipe state in Go (1.5).

While writing on a mkfifo created pipe, I try to get the state of this output pipe:

  • using the Write return status EPIPE
  • using the Write return status EPIPE and signal.Ignore on SIGPIPE (just in case)
  • using signal.Notify on SIGPIPE

I can see that:

  • EPIPE is never returned
  • when I use kill -13, the signal handler is called: “Got signal: broken pipe”
  • when I ctrl-c the reader, the signal handler is not called and my program exits with output: “signal: broken pipe”

Would you, please, indicate my error ?

JavaScript

Note: as a simple Go exercise, I try to implement a command which almost acts like tee -a <a_file> (print stdin to stdout and <a_file>) with the following specificity: non blocking write on a named pipe and optional reader.

Advertisement

Answer

The error returned is not a plain syscall.Error but instead wrapped within *os.PathError as illustrated with the following variation of your code:

JavaScript

Running this after doing mkfifo /tmp/test; head /tmp/test elsewhere gives me:

JavaScript

After returning ten pipe errors on an individual file the Go runtine stops catching/blocking SIGPIPE and lets it through to your program killing it. I don’t believe the Go runtime lets you catch or ignore SIGPIPE as it uses that signal itself internally.

So two things: one, to look for syscall.EPIPE you need to check for *os.PathError as shown and two, don’t continue on when err != nil when you haven’t actually handled the error.

I don’t know the details of why Go handles SIGPIPE in this way; perhaps a search of Go’s bug tracker and/or the go-nuts list may help answer that. With Go 1.5’s additions to the os/signal package doing signal.Reset(syscall.SIGPIPE) (before any signal.Notify calls) changes this behaviour.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement