Skip to content

Commit

Permalink
improve error handling in node_watcher (#100)
Browse files Browse the repository at this point in the history
- common.recReaddir now has an error handler (previously would crash the
  node process due to no "error" event handler)
- node_watcher and fsevents_watcher re-emit recReaddir "error" events
- node_watcher now ignores EPERM errors on win32 in more cases
  • Loading branch information
marcello3d authored and amasad committed Jul 25, 2017
1 parent 5e3a10f commit 3b6e45b
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 12 deletions.
2 changes: 2 additions & 0 deletions src/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ exports.recReaddir = function(
dirCallback,
fileCallback,
endCallback,
errorCallback,
ignored
) {
walker(dir)
Expand All @@ -97,6 +98,7 @@ exports.recReaddir = function(
})
.on('dir', normalizeProxy(dirCallback))
.on('file', normalizeProxy(fileCallback))
.on('error', errorCallback)
.on('end', function() {
if (platform === 'win32') {
setTimeout(endCallback, 1000);
Expand Down
1 change: 1 addition & 0 deletions src/fsevents_watcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ function FSEventsWatcher(dir, opts) {
filepath => (this._tracked[filepath] = true),
filepath => (this._tracked[filepath] = true),
this.emit.bind(this, 'ready'),
this.emit.bind(this, 'error'),
this.ignored
);
}
Expand Down
42 changes: 30 additions & 12 deletions src/node_watcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@ function NodeWatcher(dir, opts) {
this.root = path.resolve(dir);
this.watchdir = this.watchdir.bind(this);
this.register = this.register.bind(this);
this.checkedEmitError = this.checkedEmitError.bind(this);

this.watchdir(this.root);
common.recReaddir(
this.root,
this.watchdir,
this.register,
this.emit.bind(this, 'ready'),
this.checkedEmitError,
this.ignored
);
}
Expand Down Expand Up @@ -133,6 +135,31 @@ NodeWatcher.prototype.registered = function(fullpath) {
);
};

/**
* Determine if a given FS error can be ignored
*
* @private
*/
function isIgnorableFileError(error) {
return (
error.code === 'ENOENT' ||
// Workaround Windows node issue #4337.
(error.code === 'EPERM' && platform === 'win32')
);
}

/**
* Emit "error" event if it's not an ignorable event
*
* @param error
* @private
*/
NodeWatcher.prototype.checkedEmitError = function(error) {
if (!isIgnorableFileError(error)) {
this.emit('error', error);
}
};

/**
* Watch a directory.
*
Expand All @@ -152,14 +179,7 @@ NodeWatcher.prototype.watchdir = function(dir) {
);
this.watched[dir] = watcher;

// Workaround Windows node issue #4337.
if (platform === 'win32') {
watcher.on('error', function(error) {
if (error.code !== 'EPERM') {
throw error;
}
});
}
watcher.on('error', this.checkedEmitError);

if (this.root !== dir) {
this.register(dir);
Expand Down Expand Up @@ -222,10 +242,7 @@ NodeWatcher.prototype.detectChangedFile = function(dir, event, callback) {
}

if (error) {
if (
error.code === 'ENOENT' ||
(platform === 'win32' && error.code === 'EPERM')
) {
if (isIgnorableFileError(error)) {
found = true;
callback(file);
} else {
Expand Down Expand Up @@ -355,6 +372,7 @@ NodeWatcher.prototype.emitEvent = function(type, file, stat) {
this.rawEmitEvent(ADD_EVENT, path.relative(this.root, file), stats);
}.bind(this),
function endCallback() {},
this.checkedEmitError,
this.ignored
);
} else {
Expand Down

0 comments on commit 3b6e45b

Please sign in to comment.