Scott Frazer
Scott Frazer

Reputation: 2185

Where does named pipe (FIFO) data go when reader disconnects?

Let's say I have a producer.go and consumer.go. The consumer.go reads from a UNIX named pipe, and the producer writes to the named pipe.

As expected, If you start up just one of the producer or consumer programs, it hangs because there's no reader or writer on the other side of the pipe.

Now, If I start both programs, then immediately CTRL-C from the consumer, the producer continues sending data to the pipe and as far as I can tell there's no limit to the size of that data (I've sent 80MB)

If I start the consumer program again (while the producer is still running), it starts pulling data off of the named pipe, but not the data that I "missed" while the consumer program was not running.

My question is: When a reader of a named pipe disconnects, what happens to the data that's sent to the named pipe?

Here are my consumer.go and producer.go programs:

consumer.go

package main

import (
    "io"
    "io/ioutil"
    "log"
    "os"
    "syscall"
)

func main() {
    syscall.Mkfifo("fifo0", 0777)
    fp, err := os.OpenFile("fifo0", os.O_RDONLY, 0777)
    if err != nil {
        log.Fatalf("Could not open fifo0: %s", err)
    }
    tee := io.TeeReader(fp, os.Stdout)
    ioutil.ReadAll(tee)
}

producer.go

package main

import (
    "fmt"
    "io"
    "log"
    "os"
    "strings"
    "time"
)

func main() {
    dots := strings.Repeat(".", 990)
    fifo, err := os.OpenFile("fifo0", os.O_WRONLY, 0777)
    if err != nil {
        log.Fatalf("Could not open fifo0: %s", err)
    }
    defer fifo.Close()
    w := io.MultiWriter(os.Stdout, fifo)
    for i := 0; i < 8000; i++ {
        fmt.Fprintf(w, "%010d%s\n", i, dots)
        time.Sleep(time.Millisecond * 10)
    }
}

Upvotes: 2

Views: 958

Answers (1)

Beejor
Beejor

Reputation: 9408

A FIFO requires at least one source and one destination for data to get transferred anywhere. A reader alone waits to pull from someone, and a writer alone waits to send to someone. In this way, there are no gaps in a one-to-one pipe.

So if you're still trying to read or write from one end of a disconnected or nonexistent pipe, the answer is that the data is going nowhere; the pipe is "blocked" and can hold no data of its own. So it depends on how your code handles this situation.

In producer.go, the loop continues to run even when there's no longer a connection. Because Fprintf or MultiWriter don't raise a code-stopping error for whatever reason. In this case you could either add a check in the loop or an event handler for the fifo object's disconnection.

The reason it seems that there's a gap of disappearing data, is because the loop continues to iterate for i and generate strings it can't send.

Upvotes: 0

Related Questions