Date: Mon, 19 Nov 2001 15:00:04 -0800 (PST) From: Ian Dowse <iedowse@maths.tcd.ie> To: freebsd-bugs@FreeBSD.org Subject: Re: bin/24955:/usr/bin/tail -F in 4.1+ doesn't work if file inode changes (works in 4.0) Message-ID: <200111192300.fAJN04A06751@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/24955; it has been noted by GNATS.
From: Ian Dowse <iedowse@maths.tcd.ie>
To: Maxim Konovalov <maxim@macomnet.ru>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: bin/24955:/usr/bin/tail -F in 4.1+ doesn't work if file inode changes (works in 4.0)
Date: Mon, 19 Nov 2001 22:59:21 +0000
In message <20011119214750.L60209-100000@news1.macomnet.ru>, Maxim Konovalov wr
ites:
>
>What about this one:
Looks better, but unless I'm mistaken it introduces 250ms polling
even when -F is not specified; this would undo the benefit of using
kqueue in the first place.
How about something like the modified version below? It only polls
in the -F case (with a longer 1s interval), and it separates the
choice of sleep vs kqueue from the stat calls necessary for -F.
We always use kqueue if supported, but in the -F case, the kqueue
timeout is set to 1 second. By keeping `kq' open, this patch also
allows switching back to kqueue, for example if a symlink is changed
so that the path moves from an NFS to a UFS filesystem.
Note that the EVFILT_VNODE filter could probably be removed, since
it is no longer needed to notice when the file is renamed or deleted.
Ian
Index: forward.c
===================================================================
RCS file: /dump/FreeBSD-CVS/src/usr.bin/tail/forward.c,v
retrieving revision 1.27
diff -u -r1.27 forward.c
--- forward.c 1 Sep 2001 22:22:44 -0000 1.27
+++ forward.c 19 Nov 2001 22:34:00 -0000
@@ -94,10 +94,11 @@
off_t off;
struct stat *sbp;
{
- int ch, kq = -1;
+ int ch, n, kq = -1;
int action = USE_SLEEP;
struct kevent ev[2];
struct stat sb2;
+ struct timespec ts;
switch(style) {
case FBYTES:
@@ -193,9 +194,10 @@
clearerr(fp);
switch (action) {
- case ADD_EVENTS: {
- int n = 0;
- struct timespec ts = { 0, 0 };
+ case ADD_EVENTS:
+ n = 0;
+ ts.tv_sec = 0;
+ ts.tv_nsec = 0;
if (Fflag && fileno(fp) != STDIN_FILENO) {
EV_SET(&ev[n], fileno(fp), EVFILT_VNODE,
@@ -208,24 +210,27 @@
n++;
if (kevent(kq, ev, n, NULL, 0, &ts) < 0) {
- close(kq);
- kq = -1;
action = USE_SLEEP;
} else {
action = USE_KQUEUE;
}
break;
- }
case USE_KQUEUE:
- if (kevent(kq, NULL, 0, ev, 1, NULL) < 0)
+ ts.tv_sec = 1;
+ ts.tv_nsec = 0;
+ /*
+ * In the -F case we set a timeout to ensure that
+ * we re-stat the file at least once every second.
+ */
+ n = kevent(kq, NULL, 0, ev, 1, Fflag ? &ts : NULL);
+ if (n < 0)
err(1, "kevent");
-
- if (ev->filter == EVFILT_VNODE) {
- /* file was rotated, wait until it reappears */
- action = USE_SLEEP;
- } else if (ev->data < 0) {
- /* file shrank, reposition to end */
+ if (n == 0) {
+ /* timeout */
+ break;
+ } else if (ev->filter == EVFILT_READ && ev->data < 0) {
+ /* file shrank, reposition to end */
if (fseeko(fp, (off_t)0, SEEK_END) == -1) {
ierr();
return;
@@ -236,9 +241,11 @@
case USE_SLEEP:
(void) usleep(250000);
clearerr(fp);
+ break;
+ }
- if (Fflag && fileno(fp) != STDIN_FILENO &&
- stat(fname, &sb2) != -1) {
+ if (Fflag && fileno(fp) != STDIN_FILENO) {
+ if (stat(fname, &sb2) != -1) {
if (sb2.st_ino != sbp->st_ino ||
sb2.st_dev != sbp->st_dev ||
sb2.st_rdev != sbp->st_rdev ||
@@ -246,16 +253,15 @@
fp = freopen(fname, "r", fp);
if (fp == NULL) {
ierr();
- break;
- }
- *sbp = sb2;
- if (kq != -1)
+ } else {
+ *sbp = sb2;
action = ADD_EVENTS;
- } else if (kq != -1) {
- action = USE_KQUEUE;
+ }
}
+ } else {
+ /* file was rotated, wait until it reappears */
+ action = USE_SLEEP;
}
- break;
}
}
}
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200111192300.fAJN04A06751>
