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>