Three Things You Have to Know to Use FIFOs


FIFO TIL

Using FIFOs (named pipes) is a convenient way to communicate with other processes. A FIFO can be used in similar ways as an ordinary file. You can open, write, read, and close it. However, they are not the same. These are a couple of caveats you should be aware of them when using FIFOs.

A Pipe Has Its Capacity

When you write too much content to a FIFO at a time, it can get stuck because a pipe has a limited capacity. The limit depends on the implementation of the pipe. When a pipe gets filled up with data, write operations will block until the pipe is drained from the other side (or raise an error if the pipe was opened with non-blocking mode).

File.mkfifo('fifo')

Thread.new do
  File.open('fifo') do |f|
    sleep 10
    f.read
  end
end

File.write 'fifo', 'a'*65536*2
puts 'wrote!'

On most Linux machines, the output “wrote!” in the example above will show up after about 10 seconds after running this code because the File.write will block until f.read in the other thread is called.

To Send EOF, Close It

Sometimes you might want to send an end-of-file (EOF) explicitly to the other side of the pipe to tell a boundary of data. Then you have to close the pipe to send the EOF.

File.mkfifo('fifo') unless File.exist?('fifo')

Thread.new do
  loop do
    puts File.read('fifo')
  end
end

loop do
  f = File.open('fifo', 'w')
  f.write Time.now.to_s
ensure
  f&.close
  sleep 1
end

This example shows the current time every second (Ctrl+C to stop). To make the File.read in the other thread in this example, the writer on the main thread has to close the pipe to send an EOF.

Open a FIFO from Both Sides

When opening a FIFO, both sides must be opened. In other words, one side cannot be opened until the other side is being opened. The following example will never stop because the reader cannot finish opening the pipe because it is not opened for writing by anyone (Ctrl+C to stop).

File.mkfifo('fifo') unless File.exist?('fifo')
File.open 'fifo'

See Also