From: Pádraig Brady
Date: Wed, 9 Nov 2016 19:28:23 +0000 (+0000) Subject: tail: only retry file open if --retry specifed X-Git-Tag: v8.26~42 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4d45722d1160a04e4d26fd812da4e0140ad3550c;p=thirdparty%2Fcoreutils.git tail: only retry file open if --retry specifed * src/tail.c (tail_file): On failure to open a file, set ignore=true when --retry is not specified. * tests/tail-2/assert-2.sh: Adjust to the new behavior. * tests/tail-2/retry.sh: Add a test case. Also change from `tail ... && fail=1` to the more robust `returns_ 1 ...` construct which detects segfaults etc. * NEWS: Document the fix. --- diff --git a/NEWS b/NEWS index d88fbd9d4d..6dd6772dbb 100644 --- a/NEWS +++ b/NEWS @@ -63,6 +63,10 @@ GNU coreutils NEWS -*- outline -*- Previously truncation was ignored thus not outputting new data in the file. [bug introduced in coreutils-5.3.0] + tail -f will no longer continually try to open inaccessible files, + only doing so if --retry is specified. + [This bug was present in "the beginning".] + yes now handles short writes, rather than assuming all writes complete. [bug introduced in coreutils-8.24] diff --git a/src/tail.c b/src/tail.c index 66aad5b789..193e4fd7d2 100644 --- a/src/tail.c +++ b/src/tail.c @@ -1909,7 +1909,7 @@ tail_file (struct File_spec *f, uintmax_t n_units) { f->fd = -1; f->errnum = errno; - f->ignore = false; + f->ignore = ! reopen_inaccessible_files; f->ino = 0; f->dev = 0; } diff --git a/tests/tail-2/assert-2.sh b/tests/tail-2/assert-2.sh index 79d4254ccd..03ba8e2e62 100755 --- a/tests/tail-2/assert-2.sh +++ b/tests/tail-2/assert-2.sh @@ -38,7 +38,7 @@ for mode in '' '---disable-inotify'; do rm -f a foo out touch a || framework_failure_ - tail $mode --follow=name $fastpoll a foo > out 2>&1 & pid=$! + tail $mode $fastpoll -F a foo > out 2>&1 & pid=$! # Wait up to 12.7s for tail to start. echo x > a || framework_failure_ diff --git a/tests/tail-2/retry.sh b/tests/tail-2/retry.sh index 858909f65f..7829923566 100755 --- a/tests/tail-2/retry.sh +++ b/tests/tail-2/retry.sh @@ -51,7 +51,7 @@ grep -F 'tail: warning: --retry ignored' out || { cat out; fail=1; } # === Test: # The same with a missing file: expect error message and exit 1. -tail --retry missing > out 2>&1 && fail=1 +returns_ 1 tail --retry missing > out 2>&1 || fail=1 [ "$(countlines_)" = 2 ] || { cat out; fail=1; } grep -F 'tail: warning: --retry ignored' out || { cat out; fail=1; } @@ -122,18 +122,36 @@ grep -F 'no files remaining' out || { fail=1; cat out; } [ $rc = 1 ] || { fail=1; cat out; } rm -fd missing out || framework_failure_ +# === Test: +# Ensure that --follow=descriptor (without --retry) does *not* try +# to open a file after an initial fail, even when there are other +# tailable files. This was an issue in <= 8.25. +touch existing || framework_failure_ +tail $mode $fastpoll --follow=descriptor missing existing >out 2>&1 & pid=$! +retry_delay_ wait4lines_ .1 6 2 || { cat out; fail=1; } +[ "$(countlines_)" = 2 ] || { fail=1; cat out; } +grep -F 'cannot open' out || { fail=1; cat out; } +echo "Y" > missing || framework_failure_ +echo "X" > existing || framework_failure_ +retry_delay_ wait4lines_ .1 6 3 || { cat out; fail=1; } +[ "$(countlines_)" = 3 ] || { fail=1; cat out; } +grep '^X$' out || { fail=1; cat out; } +grep '^Y$' out && { fail=1; cat out; } +cleanup_ +rm -f missing out existing || framework_failure_ + # === Test: # Ensure that --follow=descriptor (without --retry) does *not wait* for the # file to appear. Expect 2 lines in the output file ("cannot open" + # "no files remaining") and exit status 1. -tail $mode --follow=descriptor missing >out 2>&1 && fail=1 +returns_ 1 tail $mode --follow=descriptor missing >out 2>&1 || fail=1 [ "$(countlines_)" = 2 ] || { fail=1; cat out; } grep -F 'cannot open' out || { fail=1; cat out; } grep -F 'no files remaining' out || { fail=1; cat out; } # === Test: # Likewise for --follow=name (without --retry). -tail $mode --follow=name missing >out 2>&1 && fail=1 +returns_ 1 tail $mode --follow=name missing >out 2>&1 || fail=1 [ "$(countlines_)" = 2 ] || { fail=1; cat out; } grep -F 'cannot open' out || { fail=1; cat out; } grep -F 'no files remaining' out || { fail=1; cat out; }