[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: tail aborts while following by name if using inotify
From: |
Jim Meyering |
Subject: |
Re: tail aborts while following by name if using inotify |
Date: |
Mon, 28 Dec 2009 14:10:18 +0100 |
Rob Wortman wrote:
> I have noticed a behavioral quirk in versions of tail which use inotify.
> When following a file by name (using tail -F or tail --follow=name),
> tail will abort when a file returns after being renamed. I see that this
> bug was addressed in coreutils-8.1, but I still find the behavior in
> coreutils-8.2.
>
> The most illustrative way that I've found to demonstrate what I see is
> as follows:
>
> $ touch file; tail -F file & echo $! > pid
> [1] 26527
> $ while [[ "$( ps ho comm "$(<pid)" )" == tail ]]; do mv file file1; touch
> file; done
> tail: `file' has become inaccessible: No such file or directory
> tail: `file' has appeared; following end of new file
> <repeat previous 2 lines 7 more times>
> tail: `file' has become inaccessible: No such file or directory
> [1]+ Aborted (core dumped) tail -F file
>
> The backtrace from the core dump:
> #0 0x00007ff6ed4f5ec5 in raise () from /lib/libc.so.6
> #1 0x00007ff6ed4f73c1 in abort () from /lib/libc.so.6
> #2 0x000000000040685e in hash_insert ()
> #3 0x0000000000403532 in tail_forever_inotify ()
> #4 0x0000000000404b9d in main ()
>
> In the while loop at the end of tail_forever_inotify, if hash_insert
> does not abort, recheck is called immediately after, which will print
> the "following end of new file" message. So, I can tell how many times
> hash_insert succeeds. This is significant because in the above example,
> hash_insert always succeeds 8 times and fails on the 9th.
>
> The number of successes is inversely proportional to the number of files
> that tail is watching. If tail is watching 9 or more files, it succeeds
> 0 times, and aborts the first time a moved file returns. This example
> requires no loops:
>
> $ touch file{1..9}; tail -qF file* &
> [1] 16341
> $ mv file1 wombat
> tail: `file1' has become inaccessible: No such file or directory
> $ touch file1
> $ ls
> core file1 file2 file3 file4 file5 file6 file7 file8 file9 wombat
> [1]+ Aborted (core dumped) tail -qF file*
>
> I have also noticed that tail does not exhibit this behavior when a
> watched file is removed and recreated, or when one is moved and moved
> back: I can only reproduce this by moving a file and recreating it.
Thanks for the detailed report!
I've figured out what's going on, but don't have a fix yet.
The trouble is that tail is violating the contract with the hash module
by changing a key value (the File_spec.wd member) in an element in the
hash table. When insertion requires a rehash (because the new entry
is not in the table), hash_insert aborts when the new entry is not in
the rehashed table. Obviously, if it's not in the pre-rehash table,
it must not be in the post-rehash one. But since tail.c changes a key
behind the hash module's back, it gets what it deserves ;-)
This will be fixed for the upcoming coreutils-8.3 release.