From owner-freebsd-bugs Mon Nov 19 15: 0:21 2001 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id E9A4B37B418 for ; Mon, 19 Nov 2001 15:00:04 -0800 (PST) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.4/8.11.4) id fAJN04A06751; Mon, 19 Nov 2001 15:00:04 -0800 (PST) (envelope-from gnats) Date: Mon, 19 Nov 2001 15:00:04 -0800 (PST) Message-Id: <200111192300.fAJN04A06751@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org Cc: From: Ian Dowse Subject: Re: bin/24955:/usr/bin/tail -F in 4.1+ doesn't work if file inode changes (works in 4.0) Reply-To: Ian Dowse Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org The following reply was made to PR bin/24955; it has been noted by GNATS. From: Ian Dowse To: Maxim Konovalov 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