summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/tail.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/src/tail.c b/src/tail.c
index f916d7460..2fa0ae048 100644
--- a/src/tail.c
+++ b/src/tail.c
@@ -1429,8 +1429,8 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files,
/* It's fine to add the same directory more than once.
In that case the same watch descriptor is returned. */
f[i].parent_wd = inotify_add_watch (wd, dirlen ? f[i].name : ".",
- (IN_CREATE | IN_MOVED_TO
- | IN_ATTRIB));
+ (IN_CREATE | IN_DELETE
+ | IN_MOVED_TO | IN_ATTRIB));
f[i].name[dirlen] = prev;
@@ -1619,9 +1619,16 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files,
fspec = &(f[j]);
- /* Adding the same inode again will look up any existing wd. */
- int new_wd = inotify_add_watch (wd, f[j].name, inotify_wd_mask);
- if (new_wd < 0)
+ int new_wd = -1;
+ bool deleting = !! (ev->mask & IN_DELETE);
+
+ if (! deleting)
+ {
+ /* Adding the same inode again will look up any existing wd. */
+ new_wd = inotify_add_watch (wd, f[j].name, inotify_wd_mask);
+ }
+
+ if (! deleting && new_wd < 0)
{
if (errno == ENOSPC || errno == ENOMEM)
{
@@ -1639,7 +1646,8 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files,
}
/* This will be false if only attributes of file change. */
- bool new_watch = fspec->wd < 0 || new_wd != fspec->wd;
+ bool new_watch;
+ new_watch = (! deleting) && (fspec->wd < 0 || new_wd != fspec->wd);
if (new_watch)
{
@@ -1683,7 +1691,7 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files,
if (! fspec)
continue;
- if (ev->mask & (IN_ATTRIB | IN_DELETE_SELF | IN_MOVE_SELF))
+ if (ev->mask & (IN_ATTRIB | IN_DELETE | IN_DELETE_SELF | IN_MOVE_SELF))
{
/* Note for IN_MOVE_SELF (the file we're watching has
been clobbered via a rename) we leave the watch
@@ -1695,6 +1703,14 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files,
hash_delete (wd_to_name, fspec);
}
+ /* Note we get IN_ATTRIB for unlink() as st_nlink decrements.
+ The usual path is a close() done in recheck() triggers
+ an IN_DELETE_SELF event as the inode is removed.
+ However sometimes open() will succeed as even though
+ st_nlink is decremented, the dentry (cache) is not updated.
+ Thus we depend on the IN_DELETE event on the directory
+ to trigger processing for the removed file. */
+
recheck (fspec, false);
continue;