Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Saving changed file triggers remove_self #58

Closed
hamoid opened this issue Jul 20, 2019 · 5 comments
Closed

Saving changed file triggers remove_self #58

hamoid opened this issue Jul 20, 2019 · 5 comments
Assignees
Labels

Comments

@hamoid
Copy link

hamoid commented Jul 20, 2019

Hi, this is not necessarily an issue with inotify-cpp but maybe lack of understanding on my part on inotify.

I'm watching a single file for all events (I'm actually interested only in changes). The problem is that the event is only triggered once. This is the log when saving a change from QtCreator on the watched json file:

[notice ] open 
[notice ] close_write close 
[notice ] move_self 
[notice ] attrib 
[notice ] remove_self 

And this is what happens when I edit and save the file from vim:

[notice ] move_self 
[notice ] attrib 
[notice ] remove_self 

Both end in remove_self, which means the file will no longer be watched. Why is that happening? Also, why no modify event?

@hamoid
Copy link
Author

hamoid commented Jul 20, 2019

I see now that if I watch for the containing folder instead of the specific file, it works. I guess I need to check that the event comes from the file I care about and ignore others. Is that expected?

It would be nice to include an example of how to watch for changes on a specific file. It's not as easy as it seems because editors do all kinds of tricks when a file is being saved: they create a temporary copy, make changes to that copy, rename the old file, move the new file, then delete the old file. This may trigger 15 different notifications (if you listen for all types). And they do this in different order. How do programs watch for file changes reliably?

I came to inotify thinking that it should be the most efficient way, but now I feel that watching for datestamp changes may be more reliable and simpler.

@erikzenker
Copy link
Owner

Hi Hamoid,
thanks for giving inotify-cpp a try. Sometimes editors do unexpected things to save their files (create temporaries, move the original etc.).
I used the example provided by the project and changed it to watch for Event::all, then I watched a file: ./example/inotify_example /tmp/test/file. When I edited the file with vim I get the following output:

Event open  on "/tmp/test/file/" at 27026490926760 was triggered.
Event modify  on "/tmp/test/file" at 27026491009076 was triggered.
Event modify  on "/tmp/test/file/" at 27026491319307 was triggered.
Event attrib  on "/tmp/test/file/" at 27026491332317 was triggered.
Event close_write close  on "/tmp/test/file/" at 27026491343744 was triggered.
Event attrib  on "/tmp/test/file" at 27026491357586 was triggered.

watching the folder: ./example/inotify_example /tmp/test/, produces the following output:

Event modify  on "/tmp/test/file" at 27091692613160 was triggered.
Event attrib  on "/tmp/test/file" at 27091692636098 was triggered.
Event close_write close  on "/tmp/test/file" at 27091692645600 was triggered.
Event attrib  on "/tmp/test/file" at 27091693049574 was triggered

Does the example produces the same result for you? And how does your code differ from the example code?

If you only want notifications for modifications of a single file, then just watching that file on Event::modify should be enough. You could share your code and I could try to have a look.

@erikzenker erikzenker self-assigned this Jul 21, 2019
@hamoid
Copy link
Author

hamoid commented Jul 21, 2019

Hi @erikzenker . Thank you for writing back.

As I didn't want to install inotify-cpp in my system, I added all the .h and .cpp files to my project which is available here: https://gitlab.com/hamoid/ofjsoninotify

In my project I use https://openframeworks.cc/ (graphics) and https://uscilab.github.io/cereal/ (serialization). My goal is to detect json file changes, then unserialize that json to affect animation and graphics (so the json file becomes the "gui").

The remove_self issue I mentioned above only happened when I watched for a specific file. If I watch the enclosing folder remove_self is not triggered, so that's good. The odd thing is, today, same project, it no longer shows remove_self. But the behavior is still the same: if I watch for one file, it only detects the first change. Further changes don't trigger notifications. Is that different for you?

A theory: if you watch a file, and you save changes to it, in many editors the file is moved and a new file with the original name takes its place. The file you were watching will receive no more changes. Therefore we need to watch the enclosing folder to keep track of changes to a file, or start a new watch after each change. How does that sound like?

I also wonder if /etc/fstab have an effect on this, and the fact that I use an SSD. /tmp/ is usually mounted on a ram disk, which might behave differently?

In any case, this is a personal project and it's working well enough for me now :)

@erikzenker
Copy link
Owner

erikzenker commented Jul 21, 2019

I tested my folder example again with the qtcreator and got the following event stream:

Event open  on "/tmp/test/file" at 36189632942602 was triggered.
Event open  on "/tmp/test/#580106" at 36189633271641 was triggered.
Event create  on "/tmp/test/file.EiiCfr" at 36189633302723 was triggered.
Event modify  on "/tmp/test/file.EiiCfr" at 36189633601239 was triggered.
Event open  on "/tmp/test/file.EiiCfr" at 36189633610490 was triggered.
Event attrib  on "/tmp/test/file.EiiCfr" at 36189633617686 was triggered.
Event close_write close  on "/tmp/test/file" at 36189634007734 was triggered.
Event modify  on "/tmp/test/file.EiiCfr" at 36189634019108 was triggered.
Event close_write close  on "/tmp/test/file.EiiCfr" at 36189634452809 was triggered.
Event moved_from  on "/tmp/test/file" at 36189634464081 was triggered.
Event moved_to  on "/tmp/test/file~" at 36189634472089 was triggered.
Event close_write close  on "/tmp/test/#580106" at 36189634680183 was triggered.
Event moved_from  on "/tmp/test/file.EiiCfr" at 36189634692145 was triggered.
Event moved_to  on "/tmp/test/file" at 36189634709353 was triggered.
Event remove  on "/tmp/test/file~" at 36189634717842 was triggered.

As we already assumed, the qtcreator is creating temporaries and moves them onto the original file. Such that, the original file will be removed and also its watch.

Currently, the library can't rewatch files in the event handler. I created a ticket #43 which should add this functionality.

@hamoid
Copy link
Author

hamoid commented Jul 31, 2019

Now I remember that years ago I figured out this behavior and then I forgot :)

It might be nice to document somewhere the difference between watching a file and watching it's parent folder (watching the file may stop when saving it with editors that create a new file and rename it). Cheers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants