From 3b997a9bcb05198c880e5d1605a3c96c1d7f9c5d Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Sun, 15 Nov 2009 09:25:29 +0100 Subject: tail -F can fail to track a file after it's been rotated Tailing forever and by-name (--follow=name, -F), tail would sometimes fail to follow a file that had been removed via rename. If you can't apply this patch and have tail 7.6 or newer, you can work around the bug via the undocumented --disable-inotify option. * src/tail.c (tail_forever_inotify): When tailing by name (-F), do not un-watch a file upon receipt of the IN_MOVE_SELF event. Reported by Arjan Opmeer in http://bugs.debian.org/548439. * NEWS (Bug fixes): Mention it. Also see http://marc.info/?l=coreutils-bug&m=125829031916515 * tests/Makefile.am (TESTS): Add tail-2/inotify-rotate. * tests/tail-2/inotify-rotate: New test. --- NEWS | 5 +++++ THANKS | 3 ++- src/tail.c | 8 ++++++- tests/Makefile.am | 1 + tests/tail-2/inotify-rotate | 55 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 70 insertions(+), 2 deletions(-) create mode 100755 tests/tail-2/inotify-rotate diff --git a/NEWS b/NEWS index c9fe6caae..e3763cd19 100644 --- a/NEWS +++ b/NEWS @@ -48,6 +48,11 @@ GNU coreutils NEWS -*- outline -*- were first renamed or unlinked or never modified. [The race was introduced in coreutils-7.5] + tail -F (inotify-enabled) now consistently tails a file that has been + replaced via renaming. That operation provokes either of two sequences + of inotify events. The less common sequence is now handled as well. + [The bug came with the implementation change in coreutils-7.5] + timeout now doesn't exit unless the command it is monitoring does, for any specified signal. [bug introduced in coreutils-7.0]. diff --git a/THANKS b/THANKS index 7955da76c..f9bc47639 100644 --- a/THANKS +++ b/THANKS @@ -52,6 +52,7 @@ Andy Longton alongton@metamark.com Anthony Thyssen anthony@griffith.edu.au Antonio Rendas ajrendas@yahoo.com Ariel Faigon ariel@cthulhu.engr.sgi.com +Arjan Opmeer arjan.opmeer@gmail.com Arne H. Juul arnej@solan.unit.no Arne Henrik Juul arnej@imf.unit.no Arnold Robbins arnold@skeeve.com @@ -401,7 +402,7 @@ Max Chang maxchang@ucla.edu Meelis Roos mroos@tartu.cyber.ee Michael michael@aplatform.com Michael ??? michael@roka.net -Michael Bacarella mbac@netgraft.com> +Michael Bacarella mbac@netgraft.com Michael Deutschmann michael@talamasca.ocis.net Michael Elizabeth Chastain mec.gnu@mindspring.com Michael Gaughen mgaughen@polyserve.com diff --git a/src/tail.c b/src/tail.c index 09afeec99..9a2f5ae82 100644 --- a/src/tail.c +++ b/src/tail.c @@ -1404,7 +1404,13 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files, if (ev->mask & (IN_ATTRIB | IN_DELETE_SELF | IN_MOVE_SELF)) { - if (ev->mask & (IN_DELETE_SELF | IN_MOVE_SELF)) + /* For IN_DELETE_SELF, we always want to remove the watch. + However, for IN_MOVE_SELF (the file we're watching has + been clobbered via a rename), when tailing by NAME, we + must continue to watch the file. It's only when following + by file descriptor that we must remove the watch. */ + if ((ev->mask & IN_DELETE_SELF) + || ((ev->mask & IN_MOVE_SELF) && follow_mode == Follow_descriptor)) { inotify_rm_watch (wd, f[i].wd); hash_delete (wd_table, &(f[i])); diff --git a/tests/Makefile.am b/tests/Makefile.am index f74d0a10b..fe8f34754 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -80,6 +80,7 @@ TESTS = \ rm/ext3-perf \ rm/cycle \ cp/link-heap \ + tail-2/inotify-rotate \ chmod/no-x \ chgrp/basic \ rm/dangling-symlink \ diff --git a/tests/tail-2/inotify-rotate b/tests/tail-2/inotify-rotate new file mode 100755 index 000000000..f45486aa9 --- /dev/null +++ b/tests/tail-2/inotify-rotate @@ -0,0 +1,55 @@ +#!/bin/sh +# ensure that tail -F handles rotation + +# Copyright (C) 2009 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +if test "$VERBOSE" = yes; then + set -x + tail --version +fi + +. $srcdir/test-lib.sh +expensive_ + +# For details, see +# http://lists.gnu.org/archive/html/bug-coreutils/2009-11/msg00213.html + +# Perform at least this many iterations, because on multi-core systems +# the offending sequence of events can be surprisingly uncommon. +for i in $(seq 50); do + echo $i + rm -rf k x out + :>k && :>x && timeout 10 tail -F k > out 2>&1 & + pid=$! + sleep .1 + echo b > k; + # wait for b to appear in out + while :; do grep b out > /dev/null && break; done + mv x k + # wait for tail to detect the rename + while :; do grep tail: out > /dev/null && break; done + echo ok >> k + found=0 + # wait up to 10 seconds for "ok" to appear in out + for j in $(seq 100); do + grep ok out > /dev/null && { found=1; break; } + sleep 0.1 + done + kill $pid + test $found = 0 && { fail=1; cat out; break; } +done + +Exit $fail -- cgit v1.2.3-54-g00ecf