◐ Shell
clean mode source ↗

fs: do not crash when using a closed fs event watcher · nodejs/node@c09bfd8

@@ -100,7 +100,11 @@ function FSWatcher() {

100100

// after the handle is closed, and to fire both UV_RENAME and UV_CHANGE

101101

// if they are set by libuv at the same time.

102102

if (status < 0) {

103-

this._handle.close();

103+

if (this._handle !== null) {

104+

// We don't use this.close() here to avoid firing the close event.

105+

this._handle.close();

106+

this._handle = null; // make the handle garbage collectable

107+

}

104108

const error = errors.uvException({

105109

errno: status,

106110

syscall: 'watch',

@@ -120,13 +124,17 @@ util.inherits(FSWatcher, EventEmitter);

120124

// 1. Throw an Error if it's the first time .start() is called

121125

// 2. Return silently if .start() has already been called

122126

// on a valid filename and the wrap has been initialized

127+

// 3. Return silently if the watcher has already been closed

123128

// This method is a noop if the watcher has already been started.

124129

FSWatcher.prototype.start = function(filename,

125130

persistent,

126131

recursive,

127132

encoding) {

133+

if (this._handle === null) { // closed

134+

return;

135+

}

128136

assert(this._handle instanceof FSEvent, 'handle must be a FSEvent');

129-

if (this._handle.initialized) {

137+

if (this._handle.initialized) { // already started

130138

return;

131139

}

132140

@@ -148,13 +156,18 @@ FSWatcher.prototype.start = function(filename,

148156

}

149157

};

150158151-

// This method is a noop if the watcher has not been started.

159+

// This method is a noop if the watcher has not been started or

160+

// has already been closed.

152161

FSWatcher.prototype.close = function() {

162+

if (this._handle === null) { // closed

163+

return;

164+

}

153165

assert(this._handle instanceof FSEvent, 'handle must be a FSEvent');

154-

if (!this._handle.initialized) {

166+

if (!this._handle.initialized) { // not started

155167

return;

156168

}

157169

this._handle.close();

170+

this._handle = null; // make the handle garbage collectable

158171

process.nextTick(emitCloseNT, this);

159172

};

160173