Version 0 of FIFO

Updated 2001-02-07 10:43:44

In an interesting c.l.t posting, Colin Macleod describes what it takes to make a Unix FIFO or named piped event-based:


I happen to be working on a project just now where I want to have an event-driven Tcl process read from a fifo. (This is on Solaris 2.6, in case it makes a difference.) My first attempts suggested that this could only be done by polling, but after digging around more I found that I could get fileevent to work as follows:

 proc readpipe pipe {
   set data [read $pipe]
   ... process $data ...
 }

 ### Open the fifo, set up event-driven input from it.
 proc open_pipe pipename {
   exec /bin/sh -c "sleep 10 > $pipename" &
   set pipe [open $pipename r]
   fconfigure $pipe -blocking 0
   fileevent $pipe readable [list readpipe $pipe]
   set dummy [open $pipename w]
   after 20000 {exec /bin/true}; # to get zombie sleep reaped
 }

The tricky bits are:

  1. The process opening the fifo to read will block until another process opens it to write. I get past this by exec-ing a shell which opens the pipe, writes nothing, then exits after 10 seconds. Note - it is critical that the "> $pipename" redirection is done by the shell (after it is forked as a new process) and not by Tcl.
  2. If the fifo is closed by the writing process, fileevent will fire continuously because it sees end-of-file on the fifo. We can avoid this by making sure that at least one process always has the fifo open for writing, so I also open the fifo for writing from the same Tcl process and never write to it or close it. The 10-second delay in step 1 is to give this time to happen.
  3. Finally, I noticed that the exec-ed shell would hang around as a zombie after the sleep finished. The delayed and apparently pointless exec at the end is because running exec again has the side-effect of wait-ing for terminated background processes - documented under Tcl_DetachPids(3).

(Explain how general file append operations can be detected as events only through polling.)