Skip to content
This repository has been archived by the owner on Mar 4, 2020. It is now read-only.

fix: use self instead of this inside FSWatcher onchange callback #97

Merged
merged 1 commit into from
Mar 23, 2019
Merged

Conversation

shiftkey
Copy link

@shiftkey shiftkey commented Mar 22, 2019

To reproduce this behaviour on Electron 3.1.x, I have a test project setup (on Windows, but I don't think that matters here):

$ git clone https://github.com/shiftkey/electron-quick-start -b repro-fswatcher-this-issue
$ npm install
$ npm start

Open the dev tools, click the Click me! button, see the app break into your code:

Screen Shot 2019-03-22 at 4 14 56 PM

Browse to the source of fs.js and put a break point inside FSWatcher's this._handle.onchange` callback (line 1382):

Screen Shot 2019-03-22 at 4 15 33 PM

Resume the app and it should hit the fs.js breakpoint. Check the local scope:

Screen Shot 2019-03-22 at 4 16 50 PM

Note that this inside the callback is the FSEvent associated with the onchange event, not the current FSWatcher. Further down the code uses self.* to emit events, and I think this was just a code path that rarely gets exercised.

I haven't triggered the specific code path because it requires the underlying filesystem to return a negative status value, but I know of these two issues in the wild that can be traced to this:

Let me know if this isn't the right branch to target for the PR, and if there's anything else I can do to expedite this fix into the main Electron repository.

onchange callback sets this to the reported FSEvent rather than the
outer FSWatcher
@shiftkey shiftkey changed the title use self instead of this inside FSWatcher change callback fix: use self instead of this inside FSWatcher change callback Mar 22, 2019
@shiftkey shiftkey changed the title fix: use self instead of this inside FSWatcher change callback fix: use self instead of this inside FSWatcher onchange callback Mar 22, 2019
@shiftkey
Copy link
Author

shiftkey commented Mar 22, 2019

A quick check of later versions of Electron and this code has been moved (with the self removed):

this._handle.onchange = (status, eventType, filename) => {
// TODO(joyeecheung): we may check self._handle.initialized here
// and return if that is false. This allows us to avoid firing the event
// after the handle is closed, and to fire both UV_RENAME and UV_CHANGE
// if they are set by libuv at the same time.
if (status < 0) {
if (this._handle !== null) {
// We don't use this.close() here to avoid firing the close event.
this._handle.close();
this._handle = null; // make the handle garbage collectable
}
const error = errors.uvException({
errno: status,
syscall: 'watch',
path: filename
});
error.filename = filename;
this.emit('error', error);
} else {
this.emit('change', eventType, filename);
}
};

I tested out the same repro on 4.1.1 (Node 10.11.0) and it looks like this is correctly set to the FSWatcher, so no need for more forward-porting of this fix:

Screen Shot 2019-03-22 at 4 58 20 PM

Copy link
Member

@MarshallOfSound MarshallOfSound left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😢 Ah self, how I don't miss you now we have arrow functions 😀

Fix looks good to me 👍

Copy link
Member

@codebytere codebytere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for catching this @shiftkey!

@bpasero
Copy link
Contributor

bpasero commented Mar 23, 2019

@shiftkey awesome description and PR, looking forward to this landing in Electron 3.x 👍

Copy link
Member

@ckerr ckerr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice detective work @shiftkey! Thanks for the patch!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants