-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Call callback directly to avoid unwanted preemption. #36
Conversation
@trevnorris @rvagg Do you guys have any comments on the correctness of this? The test failure on node v0.11.x is just a false-negative from AppVeyor. The Travis tests are all passing. |
|
@trevnorris That's basically what I learned/concluded with my brush with MakeCallback. (I started out with a post to the nodejs mailing list before I realized the only way I was triggering that problem was node-weak, and filing #35). Aside from node-weak, but following on what you just said about the proper use of |
@metamatt There are guards in place that should prevent issues if it's called unnecessarily. If it's not then we don't have the proper guards in place. The only impact calling |
@trevnorris Please stop me if I'm wrong: I see effects much worse than that. Check out my preemption demo (single file, then you need to |
Nan's NanCallback::Call goes through Node's MakeCallback, which is designed to be used only by event callbacks (i.e. functions called from the libuv event loop), not invoked synchronously from a call stack where JS code was already running. This is because when MakeCallback returns it assumes it's the end of the current "tick", so it calls not only the callback you told it to, but also all tick callbacks registered for the current tick. Since node-weak's TargetCallback is invoked from GC, which could be invoked from anywhere at any time, the code it calls into (the callback attached to each weakref object) needs to be designed and written carefully, essentially to the standards of signal or interrupt handlers, since they preempt any JS code that was already running when GC kicked in. This is fine as long as the weakref callbacks are written to this standard, but it also means TargetCallback needs to avoid accidentally calling other callbacks that weren't written to this standard. The fix is to call the callback directly, instead of via MakeCallback. Fixes TooTallNate#35.
0eef9bd
to
5341887
Compare
@metamatt I'll take a look into this. Not this week, but this is something that needs to be addressed. |
Sorry, couldn't resist :D |
Cool, no rush. If it's survived this long in its current state, I think it's more important to get it right than to get it changed immediately. Glad to have your attention on it (both @trevnorris, @TooTallNate). Most of the discussion here has been about the design/usage/safety of
|
You're just going to get into trouble with 0.11,0.12 support here aren't you? we had to pull |
@rvagg: I'm certainly no expert in the difference between node and V8 API versions that NAN handles. But the patch I'm proposing here seems to work fine with node 0.11.14 (as well as 0.10.32 and 0.10.26). Looking at the NanCallback code, my patch is leveraging it heavily, trying to get the same underlying So that's all to say that the patch I'm proposing here seems to compile and work fine against current 0.10 and 0.11 releases, but I don't fully understand and might be missing the concern you're raising. And is it ok to use GetFunction the way I am; why can't Maybe NanCallback should offer separate |
Yes, I think it's time to get this PR merged please. Nobody should be using node-weak without this fix. I'm using this same patch with Node.js 0.12.0 and it's working fine. I filed nodejs/nan#284 asking that |
Call callback directly to avoid unwanted preemption.
To close the loop on the discussion in #36 (comment), I filed nodejs/node-v0.x-archive#9245. |
Nan's NanCallback::Call goes through Node's MakeCallback, which is
designed to be used only by event callbacks (i.e. functions called
from the libuv event loop), not invoked synchronously from a call
stack where JS code was already running. This is because when
MakeCallback returns it assumes it's the end of the current "tick", so
it calls not only the callback you told it to, but also all tick
callbacks registered for the current tick.
Since node-weak's TargetCallback is invoked from GC, which could be
invoked from anywhere at any time, the code it calls into (the
callback attached to each weakref object) needs to be designed and
written carefully, essentially to the standards of signal or interrupt
handlers, since they preempt any JS code that was already running when
GC kicked in.
This is fine as long as the weakref callbacks are written to this
standard, but it also means TargetCallback needs to avoid accidentally
calling other callbacks that weren't written to this standard.
The fix is to call the callback directly, instead of via MakeCallback.
Fixes #35.