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

Mac: fs.watch() not detecting changes to file from git operation #5039

Closed
bpasero opened this issue Feb 2, 2016 · 8 comments
Closed

Mac: fs.watch() not detecting changes to file from git operation #5039

bpasero opened this issue Feb 2, 2016 · 8 comments
Labels
fs Issues and PRs related to the fs subsystem / file system. macos Issues and PRs related to the macOS platform / OSX.

Comments

@bpasero
Copy link
Contributor

bpasero commented Feb 2, 2016

I am on Mac OS X 10.11.1 with node.js 4.1.1. I also tried with node.js 5.x:

Steps:

  • create a folder with one file in it and enable git in that folder
  • commit to master
  • create other branch, make some changes to the file and commit to other branch
  • switch between the branches while checking the output of the following script:
var fs = require("fs");

var watcher = fs.watch('<path to file>');
watcher.on('change', function(eventtype) {
    console.log(eventtype);
});

=> I get a rename event for the first time I switch to the other branch. After that, the events stop when switching branches.

@fl0w
Copy link

fl0w commented Feb 2, 2016

fs.watch is known to have its quirks (I'm not sure why but I think it has to do with cross OS compatibility?).

chokidar is one solution from user-land.

@imyller
Copy link
Member

imyller commented Feb 2, 2016

If the file gets deleted and immediately recreated, fs.watch loses it.

One workaround for this is to watch the parent directory of the file.

Something like this:

function watchFile(filepath, callback) {
    var fpath = path.resolve(filepath),
          fdir = path.dirname(fpath),
          fname = path.basename(fpath);
    fs.statSync(fdir);
    return fs.watch(fdir, {persistent: false, recursive: false}, function (event, changed_fname) {
        if (changed_fname === fname) {
            fs.stat(fpath, function (err) {
                callback && callback(null, !err, fpath);
            });
        }
    });
}

@Fishrock123 Fishrock123 added the question Issues that look for answers. label Feb 2, 2016
@mscdex mscdex added macos Issues and PRs related to the macOS platform / OSX. fs Issues and PRs related to the fs subsystem / file system. and removed question Issues that look for answers. labels Feb 2, 2016
@jorangreef
Copy link
Contributor

@bpasero I think @imyller's explanation is correct. It's not a bug or issue with fs.watch.

It's just how paths and inodes work on OS X and Linux. The watch is actually watching the inode of the file and not the path of the file as far as I understand. The inode is resolved from the path of the file when the file is first watched.

When the file is deleted, the watch remains on the inode of the deleted file. When the file is recreated by git it actually gets assigned a different inode, which is why changes to this file are no longer picked up by the watch (which is still watching the old deleted inode). One can confirm this by calling stat -s filepath and comparing st_ino after creating and recreating the file.

It would be better to have a recursive watch on the root of the file tree that you're interested in as @imyller suggested. This way you'll always pick up changes to children and descendants regardless of their inodes changing. It's also less resource intensive.

@jasnell
Copy link
Member

jasnell commented Apr 3, 2016

Closing as this is not a bug. It may be worthwhile to have some more documentation around this, however. /cc @nodejs/documentation

@jasnell jasnell closed this as completed Apr 3, 2016
@stevemao
Copy link
Contributor

stevemao commented Apr 5, 2016

@jorangreef would you like to do a PR?

@jorangreef
Copy link
Contributor

@stevemao sure, working on it now.

@jorangreef
Copy link
Contributor

Done: #6099

@Knighton910
Copy link

👍 @jorangreef

Done: #6099

jasnell pushed a commit that referenced this issue Apr 18, 2016
On Linux and OS X systems, `fs.watch()` resolves the watched path to an
inode. This clarifies that `fs.watch()` watches the inode and not the
path. If the inode of the path subsequently changes, `fs.watch()` will
continue watching the original inode and events for the path will no
longer be emitted. This is expected behavior.

Fixes: #5039
PR-URL: #6099
Reviewed-By: James M Snell <[email protected]>
MylesBorins pushed a commit that referenced this issue Apr 19, 2016
On Linux and OS X systems, `fs.watch()` resolves the watched path to an
inode. This clarifies that `fs.watch()` watches the inode and not the
path. If the inode of the path subsequently changes, `fs.watch()` will
continue watching the original inode and events for the path will no
longer be emitted. This is expected behavior.

Fixes: #5039
PR-URL: #6099
Reviewed-By: James M Snell <[email protected]>
MylesBorins pushed a commit that referenced this issue Apr 20, 2016
On Linux and OS X systems, `fs.watch()` resolves the watched path to an
inode. This clarifies that `fs.watch()` watches the inode and not the
path. If the inode of the path subsequently changes, `fs.watch()` will
continue watching the original inode and events for the path will no
longer be emitted. This is expected behavior.

Fixes: #5039
PR-URL: #6099
Reviewed-By: James M Snell <[email protected]>
MylesBorins pushed a commit that referenced this issue Apr 20, 2016
On Linux and OS X systems, `fs.watch()` resolves the watched path to an
inode. This clarifies that `fs.watch()` watches the inode and not the
path. If the inode of the path subsequently changes, `fs.watch()` will
continue watching the original inode and events for the path will no
longer be emitted. This is expected behavior.

Fixes: #5039
PR-URL: #6099
Reviewed-By: James M Snell <[email protected]>
MylesBorins pushed a commit that referenced this issue Apr 20, 2016
On Linux and OS X systems, `fs.watch()` resolves the watched path to an
inode. This clarifies that `fs.watch()` watches the inode and not the
path. If the inode of the path subsequently changes, `fs.watch()` will
continue watching the original inode and events for the path will no
longer be emitted. This is expected behavior.

Fixes: #5039
PR-URL: #6099
Reviewed-By: James M Snell <[email protected]>
MylesBorins pushed a commit that referenced this issue Apr 21, 2016
On Linux and OS X systems, `fs.watch()` resolves the watched path to an
inode. This clarifies that `fs.watch()` watches the inode and not the
path. If the inode of the path subsequently changes, `fs.watch()` will
continue watching the original inode and events for the path will no
longer be emitted. This is expected behavior.

Fixes: #5039
PR-URL: #6099
Reviewed-By: James M Snell <[email protected]>
joelostrowski pushed a commit to joelostrowski/node that referenced this issue Apr 25, 2016
On Linux and OS X systems, `fs.watch()` resolves the watched path to an
inode. This clarifies that `fs.watch()` watches the inode and not the
path. If the inode of the path subsequently changes, `fs.watch()` will
continue watching the original inode and events for the path will no
longer be emitted. This is expected behavior.

Fixes: nodejs#5039
PR-URL: nodejs#6099
Reviewed-By: James M Snell <[email protected]>
jasnell pushed a commit that referenced this issue Apr 26, 2016
On Linux and OS X systems, `fs.watch()` resolves the watched path to an
inode. This clarifies that `fs.watch()` watches the inode and not the
path. If the inode of the path subsequently changes, `fs.watch()` will
continue watching the original inode and events for the path will no
longer be emitted. This is expected behavior.

Fixes: #5039
PR-URL: #6099
Reviewed-By: James M Snell <[email protected]>
MylesBorins pushed a commit that referenced this issue May 3, 2016
On Linux and OS X systems, `fs.watch()` resolves the watched path to an
inode. This clarifies that `fs.watch()` watches the inode and not the
path. If the inode of the path subsequently changes, `fs.watch()` will
continue watching the original inode and events for the path will no
longer be emitted. This is expected behavior.

Fixes: #5039
PR-URL: #6099
Reviewed-By: James M Snell <[email protected]>
MylesBorins pushed a commit that referenced this issue May 6, 2016
On Linux and OS X systems, `fs.watch()` resolves the watched path to an
inode. This clarifies that `fs.watch()` watches the inode and not the
path. If the inode of the path subsequently changes, `fs.watch()` will
continue watching the original inode and events for the path will no
longer be emitted. This is expected behavior.

Fixes: #5039
PR-URL: #6099
Reviewed-By: James M Snell <[email protected]>
MylesBorins pushed a commit that referenced this issue May 18, 2016
On Linux and OS X systems, `fs.watch()` resolves the watched path to an
inode. This clarifies that `fs.watch()` watches the inode and not the
path. If the inode of the path subsequently changes, `fs.watch()` will
continue watching the original inode and events for the path will no
longer be emitted. This is expected behavior.

Fixes: #5039
PR-URL: #6099
Reviewed-By: James M Snell <[email protected]>
bors bot added a commit to comit-network/comit-rs that referenced this issue Feb 6, 2020
1994: api_test: Fix bitcoind/parity log wait r=D4nte a=D4nte

There are issues on Mac where it waits undefinitely for the right light for both nodes despite the line being present in the file.

See nodejs/node#5039 for more info.

Co-authored-by: Franck Royer <[email protected]>
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. macos Issues and PRs related to the macOS platform / OSX.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants