Date: Wed, 21 Nov 2001 14:00:02 -0800 (PST) From: Maxim Konovalov <maxim@macomnet.ru> 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: <200111212200.fALM02O99854@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: Maxim Konovalov <maxim@macomnet.ru> To: Ian Dowse <iedowse@maths.tcd.ie> 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: Thu, 22 Nov 2001 00:50:37 +0300 (MSK) Hello Ian, On Mon, 19 Nov 2001, Ian Dowse wrote: > 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. Looks OK for me except one minor problem, see below > 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); + if (kq != -1) + action = ADD_EVENTS; It will help to break USE_SLEEP cycle when you remove symlink to fname and recreate it again. Of course it will break automatically when new data arrives but it may never happen. > + 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; > } > } > } > > There is still an issue when fname is renamed. Our tail will continue read data from the renamed file in USE_SLEEP cycle until a new fname appear. The old tail (RELENG_4_0_0_RELEASE f.e.) works in the same way. Imho it is not a correct behaviour but I am not quite sure. -- Maxim Konovalov, MAcomnet, Internet-Intranet Dept., system engineer phone: +7 (095) 796-9079, mailto: maxim@macomnet.ru 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?200111212200.fALM02O99854>