| Summary: | tail -f from a fifo goes into a busy loop after first read | ||
|---|---|---|---|
| Product: | Base System | Reporter: | Nick Johnson <freebsd> |
| Component: | kern | Assignee: | jlemon |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | 4.1.1-STABLE | ||
| Hardware: | Any | ||
| OS: | Any | ||
Responsible Changed From-To: gnats-admin->jlemon jlemon wrote kqueue and loves bug reports about it. For some reason, trying to fix the trouble by passing in a change with
EV_CLEAR set doesn't work, but freopen & re-adding the events seems to
work fine:
--- forward.c.orig Sun Nov 26 13:02:38 2000
+++ forward.c Sun Nov 26 14:15:14 2000
@@ -218,6 +218,18 @@
}
case USE_KQUEUE:
+ if ((ev->flags & EV_EOF) > 0) {
+ /* Maybe EOF on a fifo; reopen it
+ * the original is closed so the events
+ * are deleted
+ */
+ if ((fp = freopen(fname, "r", fp)) == NULL)
+ ierr();
+ else
+ action = ADD_EVENTS;
+ break;
+ }
+
if (kevent(kq, NULL, 0, ev, 1, NULL) < 0)
err(1, "kevent");
There may be a more elegant fix than this of course.
--
"The reasonable man adapts himself to the world; the unreasonable one
persists in trying to adapt the world to himself. Therefore all
progress depends on the unreasonable man."
-- George Bernard Shaw
Nick Johnson, version 2.0b1 http://www.spatula.net/
State Changed From-To: open->closed Fix for the problem has been committed. |
When tail -f is reading from a FIFO, after the first read, it goes into a busy loop between kevent and read. In the case where I've observed it, one process is writing to the FIFO with the descriptor set non-blocking. Following is a truss from tail -f showing what happens, minus the startup junk common to any process: sigaction(SIGILL,0xbfbffaa0,0xbfbffa88) = 0 (0x0) sigprocmask(0x1,0x0,0x2805d73c) = 0 (0x0) sigaction(SIGILL,0xbfbffa88,0x0) = 0 (0x0) sigprocmask(0x1,0x2805d700,0xbfbffac8) = 0 (0x0) sigprocmask(0x3,0x2805d710,0x0) = 0 (0x0) open("mlog",0,0666) = 3 (0x3) fstat(3,0xbfbffac4) = 0 (0x0) readlink("/etc/malloc.conf",0xbfbff904,63) ERR#2 'No such file or directory' mmap(0x0,4096,0x3,0x1002,-1,0x0) = 672112640 (0x280fa000) break(0x804d000) = 0 (0x0) break(0x804e000) = 0 (0x0) fstat(3,0xbfbff874) = 0 (0x0) break(0x804f000) = 0 (0x0) read(0x3,0x804e000,0x400) = 53 (0x35) break(0x8050000) = 0 (0x0) read(0x3,0x804e000,0x400) = 0 (0x0) 24.142.183.133 GET / write(1,0x804f000,21) = 21 (0x15) Lynx/2.8.2rel.1 libwww-FM/2.14 write(1,0x804f200,32) = 32 (0x20) kqueue() = 4 (0x4) kevent(0x4,0xbfbffa5c,0x1,0x0,0x0,0xbfbff9f4) = 0 (0x0) read(0x3,0x804e000,0x400) = 0 (0x0) kevent(0x4,0x0,0x0,0xbfbffa5c,0x1,0x0) = 1 (0x1) read(0x3,0x804e000,0x400) = 0 (0x0) kevent(0x4,0x0,0x0,0xbfbffa5c,0x1,0x0) = 1 (0x1) read(0x3,0x804e000,0x400) = 0 (0x0) (...) kevent(0x4,0x0,0x0,0xbfbffa5c,0x1,0x0) = 1 (0x1) read(0x3,0x804e000,0x400) = 0 (0x0) SIGNAL 2 SIGNAL 2 process exit, rval = 2 Fix: Sorry, I don't have a patch, as I'm not yet familiar with kqueue. How-To-Repeat: mkfifo foo tail -f foo start a process to open foo for non-blocking writing write something to foo