Sources 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 modification. 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. https://bugzilla.novell.com/show_bug.cgi?id=779531 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) bark ("inotify_add_watch"); } 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 times regularly) 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.
Hi, Maintainer I just coy some analyze from Novell's bugzilla, and could you help review the patch in comment#3? Thanks a lot!