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: https://github.com/nodejs/node/pull/8524
Fixes: https://github.com/nodejs/node/issues/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>
This commit is contained in:
Claudio Rodriguez 2016-09-06 17:34:18 +01:00 committed by Ilkka Myller
parent 0f2f8efdde
commit 1b97774c44
3 changed files with 33 additions and 1 deletions

View File

@ -1393,6 +1393,10 @@ fs.watch = function(filename, options, listener) {
// Stat Change Watchers
function emitStop(self) {
self.emit('stop');
}
function StatWatcher() {
EventEmitter.call(this);
@ -1413,7 +1417,7 @@ function StatWatcher() {
};
this._handle.onstop = function() {
self.emit('stop');
process.nextTick(emitStop, self);
};
}
util.inherits(StatWatcher, EventEmitter);

View File

@ -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);
});

View File

@ -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);