codekitchen / fsevents_to_vm

forward OS X file system events to a VM, designed for use with Dinghy
MIT License
22 stars 10 forks source link

FYI: issue with Vim and fsevents_to_vm on file events #7

Open gkop opened 8 years ago

gkop commented 8 years ago

Steps to replicate

  1. On host, open foo.js in Vim [0] with an empty .vimrc
  2. On vm, run inotifywait foo.js
  3. Edit foo.js and save in Vim

Expected behavior inotifywait reports the file has changed

Observed behavior inotifywait does not report anything

Fix for Vim is to add set backupcopy=yes to .vimrc .

Note that inotifywait on the directory containing foo.js does report an event.

Could this behavior be due to the limitation to fsevents_to_vm that Multiple events for the same file within the same 1/100th of a second may cause events to be missed.?

[0] I'm using the vim binary provided by MacVim, in my terminal.

codekitchen commented 8 years ago

This is a consequence of how fsevents_to_vm works -- it doesn't actually modify the file, just the file's metadata attributes (specifically the mtime). This shows up as an inotify ATTRIB event on the directory. This hasn't been a problem in practice because all the use cases we've cared about (guard, webpack, etc) react to these events. Are you seeing a specific problem, or were you just investigating how it worked?

gkop commented 8 years ago

Yes, I was bit by this when passing individual files to watchify.

codekitchen commented 8 years ago

In theory we could use the same de-duping logic that we have for mtime changes, but actually open up the file. I wonder if a zero-length write would trigger an event. It'd take some testing to see what we can get away with.

szlend commented 8 years ago

I've had the same issue with live reloading in Phoenix. I've tracked the issue down to this line https://github.com/synrc/fs/blob/master/src/sys/inotifywait.erl#L11

It looks like they don't watch for ATTRIB at all.

codekitchen commented 8 years ago

Good info thanks. They watch for close_write, which according to http://linux.die.net/man/1/inotifywait means "A watched file or a file within a watched directory was closed, after being opened in writeable mode. This does not necessarily imply the file was written to."

So in theory, we could open the file for writing, then immediately close it without writing anything, and it should work with Phoenix and probably most others who don't watch for attrib changes.

It'll be a while before I have time to work on this, though.

szlend commented 8 years ago

Yeah, I just tested it with open('test', 'a', &:flush) and that triggered it for me.

codekitchen commented 6 years ago

I've got a WIP branch that simulates WRITE_CLOSE events, which appears to be enough to fix this issue.

However, it doesn't look like that's good enough for the inotify.go library (and thus CompileDaemon), which doesn't watch for WRITE_CLOSE and requires an actual MODIFY event. The only way to get a modify event is to actually modify the file in the docker VM, which is of course a lot more problematic... I'll have to think about it for a while. I'm not sure what the solution could be yet.