Skip site navigation (1)Skip section navigation (2)
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>