Sourceware Bugzilla – Bug 14906
inotify failed when /etc/hosts file change
Last modified: 2012-12-03 10:44:32 UTC
Created attachment 6770 [details]
The test program
This test program shows the problem. I'm creating a watch on /etc/hosts
(looking for modification or deletion), and it's catching only changes of
the type "echo '#bla' >> /etc/hosts". It doesn't catch changes via copy
to temporary file, do changes, rename temp file back to /etc/hosts. That's
what sed -i is using to atomically do the in place changes.
I thought that adding IN_MOVE should help when setting up the watch,
but it doesn't (commented out in the test program). Even if it would have
helped I would claim the kernel to be broken. If I include IN_MODIFY
in a watch for /etc/hosts, I'm of course also interested if somebody renames
some random file to the watched filename, as it very certainly is a
Basically as soon as "sed -i" is done on the file the kernel lost track
of the watch and no changes to the "new" /etc/hosts are tracked anymore.
The original bug is from SUSE Linux.
Michael Matz's comments.
I can make the program work as expected also in the light of overwriting
renames, when I'm handling a IN_IGNORED event by recreating the watch on
/etc/hosts, like this in the inner loop:
if (buf.wd == watch && (buf.mask & IN_IGNORED) != 0)
/* Recreate watch */
watch = inotify_add_watch (fd, "/etc/hosts", IN_DELETE_SELF |
IN_MODIFY /* | IN_MOVE */);
printf ("Added watch on /etc/hosts, as watch %d\n", watch);
if (watch < 0)
That's for sure surprising limitation of the interface. Is this really how
it's supposed to be used?
Miklos Szeredi 2012-10-15 15:27:29 UTC
(In reply to comment #20)
> I can make the program work as expected also in the light of overwriting
> renames, when I'm handling a IN_IGNORED event by recreating the watch on
> /etc/hosts, like this in the inner loop:
> if (buf.wd == watch && (buf.mask & IN_IGNORED) != 0)
> /* Recreate watch */
> watch = inotify_add_watch (fd, "/etc/hosts", IN_DELETE_SELF |
> IN_MODIFY /* | IN_MOVE */);
> printf ("Added watch on /etc/hosts, as watch %d\n", watch);
> if (watch < 0)
> bark ("inotify_add_watch");
> That's for sure surprising limitation of the interface. Is this really how
> it's supposed to be used?
The watch descriptor returned by inotify_add_watch() refers to the inode, not
the path name. This is analogous to open(2) returning a file descriptor that
refers to the inode, not the pathname.
So yes, adding IN_DELETE_SELF and IN_MOVE_SELF to the watches is a good way to
monitor whether changes to the file _name_ were made.
Note: inotify is an unreliable interface by design and the application should
provide a backup mechanism for theoretical cases when events are lost (e.g. by
checking the modification time of the file periodically).
Also see "Limitations and caveats" section in the inofity(7) manpage.
Created attachment 6771 [details]
the patch for suggested fix
Miklos Szeredi 2012-10-18 11:04:49 UTC
I looked at the inotify code in nscd code and it's full of bugs. Apparently
the cache pruning by inotify wasn't tested to any useful extent. And latest
upstream version carries all those bugs too. We can fix all these but that's a
whole little project. Or there are some simpler options:
a) disable inotify completely and do it the old way (check file modification
b) enable inotify but also check modification times in case the inotify code
fails to work.
c) option b) plus something like comment 20
The attached patch does option b). I've not tested it.
The glibc package maintainers will have to make the decision on how to fix it,
this patch is just a suggestion.
I just coy some analyze from Novell's bugzilla, and could you help review the patch in comment#3? Thanks a lot!