From 21124ba23a43c057fdec983ae3e558987c28a164 Mon Sep 17 00:00:00 2001 From: Claudio Rodriguez Date: Tue, 6 Sep 2016 17:34:18 +0100 Subject: [PATCH] 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 Reviewed-By: Matteo Collina Reviewed-By: Ilkka Myller Reviewed-By: James M Snell Reviewed-By: Yorkie Liu --- lib/fs.js | 6 +++++- test/parallel/test-fs-watch-stop-async.js | 19 +++++++++++++++++++ test/parallel/test-fs-watch-stop-sync.js | 9 +++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-fs-watch-stop-async.js create mode 100644 test/parallel/test-fs-watch-stop-sync.js diff --git a/lib/fs.js b/lib/fs.js index 6e28a41118e131..5f5ccfaefbb5b2 100644 --- a/lib/fs.js +++ b/lib/fs.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); diff --git a/test/parallel/test-fs-watch-stop-async.js b/test/parallel/test-fs-watch-stop-async.js new file mode 100644 index 00000000000000..5cbfd58418024a --- /dev/null +++ b/test/parallel/test-fs-watch-stop-async.js @@ -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); +}); diff --git a/test/parallel/test-fs-watch-stop-sync.js b/test/parallel/test-fs-watch-stop-sync.js new file mode 100644 index 00000000000000..1444ff6bfd5ce3 --- /dev/null +++ b/test/parallel/test-fs-watch-stop-sync.js @@ -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);