Common lisp 从 FIFO 读取超时

Common lisp read from FIFO with timeout

所以我有一些代码像

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

据我所知,这可以正常工作,但如果没有数据写入 cur-fifo,这将无限期阻塞。如果在 ~0.1 秒左右无法读取数据,我希望读取超时并且 return NIL。

运行 在 SBCL 1.1.18 上,在 64 位 Gentoo 上 Linux

FIFO model

当你open一个fifo特殊设备(用于读取)时,系统调用阻塞除非

  • fifo 已经被(另一个)进程打开用于​​写入 OR
  • 您将 O_ASYNC 传递给 open(2) - 除非您使用低级包 sb-posix
  • ,否则您可能无法在实施中执行此操作

当你成功打开 fifo 时,你的 read(2) 调用将阻塞直到你的交易对手(打开 fifo 进行写入,这可能是同一个 lisp 进程) 在那里写一些东西。

普通 Lisp

你要找的是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))))

调试

请注意,并非所有 CL 供应商都同样支持特殊设备处理。 如果以上方法不起作用,请用 REPL 做一些实验:打开 fifo,看看 listen returns,在那里写点东西,看看 listen 现在报告了什么, &c.

如果 listen 仍然 returns nil 即使您已经在管道中写入了一些内容,这可能意味着您的 CL 无法将该文件识别为特殊设备。您可能必须将一些特定于实现的参数传递给 open,例如 :buffering nil 或其他东西(尝试 (describe 'open))。