Common lisp read from FIFO with timeout

684 Views Asked by At

So I have some code like

(let ((file (open cur-fifo :if-does-not-exist :create)))
  (format t "~A~%" (read-line file nil))
  (close file))

Which as far as I can tell works fine, except that this will block indefinitely if no data was written to cur-fifo. I want the read to time out and return NIL if no data could be read in ~0.1 sec or so.

Running on SBCL 1.1.18, on 64-bit Gentoo Linux

1

There are 1 best solutions below

8
On BEST ANSWER

FIFO model

When you open a fifo special device (for reading), the system call blocks unless either

  • the fifo is already opened by (another) process for writing OR
  • you pass O_ASYNC to open(2) - which you might not be able to do in your implementation unless you use a low level package sb-posix

When you successfully opened the fifo, your read(2) call will block until your counterparty (that opened the fifo for writing, which could be the same lisp process) writes something there.

Common Lisp

What you are looking for is listen (see also with-open-file):

(with-open-file (fifo "my-fifo" :if-does-not-exist :create)
  (when (or (listen fifo)
            (progn (sleep 0.1)
                   (listen fifo)))
    (format t "Read [~A]~%" (read-line fifo))))

Debugging

Please note that special device handling is not necessarily equally well supported by all CL vendors. If the above does not work, please do some experiments with the REPL: open the fifo, see what listen returns, write something there, see what listen reports now, &c.

If listen still returns nil even though you already wrote something into the pipe, this might mean that your CL does not recognize the file as a special device. You might have to pass some implementation-specific arguments to open, e.g., :buffering nil or something (try (describe 'open)).