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

fs.watch has double change events for file writes #3042

Closed
andy-hanson opened this issue Sep 24, 2015 · 10 comments
Closed

fs.watch has double change events for file writes #3042

andy-hanson opened this issue Sep 24, 2015 · 10 comments
Labels
fs Issues and PRs related to the fs subsystem / file system.

Comments

@andy-hanson
Copy link

Run these commands:

echo "require('fs').watch(__dirname).on('change', console.log)" > watch.js
node watch.js &
echo "" > watch.js

To get this output:

change watch.js
change watch.js

I'm running node v4.1.1 on Linux Mint 17.

@brendanashworth brendanashworth added the fs Issues and PRs related to the fs subsystem / file system. label Sep 24, 2015
@targos
Copy link
Member

targos commented Sep 24, 2015

I cannot reproduce on OSX

@silverwind
Copy link
Contributor

Also cannot reproduce on two Linux boxes.

@nwoltman
Copy link
Contributor

I was able to reproduce this consistently on Windows 7.
Tested on several versions all the way back to v0.10.0 and it was still there.

@nwoltman
Copy link
Contributor

Looks like the root of the problem is in libuv. Most likely this line is getting called twice.
Of course, it's quite possible that there's nothing wrong with libuv and it's just Windows/Mint emitting two events for the same thing.

@bnoordhuis
Copy link
Member

Might be an artifact of the file system or the kernel. I can't reproduce on 4.0.4-301.fc22.x86_64 with ext4.

Can you run strace -o trace.log node watch.js and gist the contents of trace.log? Please post the output of uname -a as well.

@andy-hanson
Copy link
Author

uname -a: Linux andy-Inspiron-3647 3.13.0-24-generic #47-Ubuntu SMP Fri May 2 23:30:00 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
For trace.log, I had to modify the command to strace -o ../trace.log node watch.js to avoid an infinite loop. Then I got this: https://gist.github.com/andy-hanson/ca73a470707ff023786e

@bnoordhuis
Copy link
Member

@andy-hanson Thanks. The salient bits:

epoll_wait(5, {{EPOLLIN, {u32=9, u64=9}}}, 1024, -1) = 1
read(9, "\1\0\0\0\2\0\0\0\0\0\0\0\20\0\0\0watch.js\0\0\0\0\0\0\0\0"..., 4096) = 64
write(10, "change watch.js\n", 16)      = 16
write(10, "change watch.js\n", 16)      = 16

The kernel is returning two 32 byte inotify events. The second one got cut off here but I'm willing to bet that if you pass -s 256 to strace, you're going to see watch.js in there twice.

@andy-hanson
Copy link
Author

@bnoordhuis Your were right. I've ran with -s 256 and updated the gist.

@bnoordhuis
Copy link
Member

Thanks. I don't think there is much we can do here, it's the kernel that delivers two distinct IN_MODIFY events.

Libuv could coalesce them but then it has to pick a completely arbitrary time window to coalesce them in. It won't prevent duplicate events, just make them less prevalent. I suggest we leave well enough alone.

@jasnell
Copy link
Member

jasnell commented Dec 30, 2015

Assuming this one is safe to close.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fs Issues and PRs related to the fs subsystem / file system.
Projects
None yet
Development

No branches or pull requests

7 participants