tek, ars & la strada ☯ॐ☢ csmr@kapsi

Ruby 2 FIFO notes

I've been obsessed over the idea of getting FIFOs - Unix style - to work for a little game-project I got going on. - After all, write/read of one byte taking 30 microseconds over a TCP-socket would take roughly 5 microseconds over a UNIX socket! This makes FIFOs the fastest IPC-method after shared memory. Here are some notes.

FIFOs are monodirectional named pipes that can be accessed using a filepath. Data sent via a FIFO is sent between processes via kernel (not fs).

Getting the "Errno::EINTR" ?

I did, while trying to get my processes to open freshly created fifos. Incidentally, Starr Horne has a very nice list of all the error codes from Errno.

Turns out the solution in Ruby 2.1 is this:

  # create a fifo
  system("mkfifo #{Pipe_ui}") unless File.exists? Pipe_ui

  # open it for reading
  begin
    @pipe_from_ui = open( Pipe_ui, "r" )
  rescue Interrupt, Errno::EINTR
    retry
  end 
It may be a good idea to add a limit to number of retries. Naturally, a writer with the same semantics is also needed! Ruby 2.4 has File.mkfifo.

Assuming the pipes have been setup, the simplest way to r/w through a FIFO-pipe is:

  ...
  # somewhere in your code
  msg = @pipe_from_ui.gets # 'puts' for the writer
  unless msg == nil
    msg.strip!
    # do stuff
  end
  ...
In another process:
  ...
  # 
  def send_fifo_msg a_string
    @pipe_from_ui.puts a_string
    @pipe_from_ui.flush
  end
  ...
I'm still wondering if one should wrap the reader & writer methods in begin-rescue semantics or not. This will have to wait until I have the time to debug it more.

Copyright C. P. - published - All Rights Reserved - Ask permission to republish.