Permalink
Browse files

fs: do not emit 'stop' watch event synchronously

Emits 'stop' event for fs.watchFile on process.nextTick
to fix 'maximum call stack size exceeded' error when
`stop` is called synchronously after listener is attached.

PR-URL: #8524
Fixes: #8421
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Ilkka Myller <ilkka.myller@nodefield.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Yorkie Liu <yorkiefixer@gmail.com>
  • Loading branch information...
claudiorodriguez authored and jasnell committed Sep 6, 2016
1 parent 9dc9074 commit 21124ba23a43c057fdec983ae3e558987c28a164
Showing with 33 additions and 1 deletion.
  1. +5 −1 lib/fs.js
  2. +19 −0 test/parallel/test-fs-watch-stop-async.js
  3. +9 −0 test/parallel/test-fs-watch-stop-sync.js
@@ -1443,6 +1443,10 @@ fs.watch = function(filename, options, listener) {
// Stat Change Watchers
function emitStop(self) {
self.emit('stop');
}
function StatWatcher() {
EventEmitter.call(this);
@@ -1463,7 +1467,7 @@ function StatWatcher() {
};
this._handle.onstop = function() {
self.emit('stop');
process.nextTick(emitStop, self);
};
}
util.inherits(StatWatcher, EventEmitter);
@@ -0,0 +1,19 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const fs = require('fs');
const watch = fs.watchFile(__filename, () => {});
let triggered;
const listener = common.mustCall(() => {
triggered = true;
});
triggered = false;
watch.once('stop', listener); // Should trigger.
watch.stop();
assert.equal(triggered, false);
setImmediate(() => {
assert.equal(triggered, true);
watch.removeListener('stop', listener);
});
@@ -0,0 +1,9 @@
'use strict';
require('../common');
const assert = require('assert');
const fs = require('fs');
const watch = fs.watchFile(__filename, () => {});
watch.once('stop', assert.fail); // Should not trigger.
watch.stop();
watch.removeListener('stop', assert.fail);

0 comments on commit 21124ba

Please sign in to comment.