On 02/04/2015 11:09 AM, 최종우 wrote: > To reproduce the problem, you can run this script. It exhausted inotify > watches. (in order to get the result more > quickly, decrease the value of max_user_watches.) > > let count=0; echo $count>>a.log; ./tail -F a.log & while true; do mv a.log > a.log.$count; let count=count+1; echo > $count>>a.log; done
The following incomplete quick-shot patch releases the old inotify resource, and reverts to polling if tail really hits ENOSPC (rather than a strange "no space left on device" message). Not tested much - at least it passes the existing tests. Currently, I've no idea how to test that properly. I've not looked closer at the other tail bug reported yesterday; does that interfere with this one? Have a nice day, Berny >From bb6f98c27962d3befb4f9507b87597d3e72b8eac Mon Sep 17 00:00:00 2001 From: Bernhard Voelker <[email protected]> Date: Thu, 5 Feb 2015 01:40:05 +0100 Subject: [PATCH] tail: avoid inotify resource leaks * src/tail.c (tail_forever_inotify): When following by name, release the inotify resource before adding a new one for the file name to watch. While at it, diagnose inotify ENOSPC errors more user-friendly and revert to polling in this case. --- src/tail.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/tail.c b/src/tail.c index b512c2a..1cc263a 100644 --- a/src/tail.c +++ b/src/tail.c @@ -1571,17 +1571,29 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files, if (j == n_files) continue; - /* It's fine to add the same file more than once. */ + fspec = &(f[j]); + + /* Remove old watch if following by name. */ + if (follow_mode == Follow_name) + inotify_rm_watch (wd, fspec->wd); + + /* Add a new watch for the file. */ int new_wd = inotify_add_watch (wd, f[j].name, inotify_wd_mask); if (new_wd < 0) { + if (errno == ENOSPC) + { + error (0, 0, _("inotify resources exhausted")); + /* Revert to polling. */ + /* FIXME: release hash and inotify resources. */ + errno = 0; + return true; + } /* Can get ENOENT for a dangling symlink for example. */ error (0, errno, _("cannot watch %s"), quote (f[j].name)); continue; } - fspec = &(f[j]); - /* Remove 'fspec' and re-add it using 'new_fd' as its key. */ hash_delete (wd_to_name, fspec); fspec->wd = new_wd; -- 2.1.4
