-
Notifications
You must be signed in to change notification settings - Fork 7.3k
node::MakeCallback is dangerous, can you detect misuse and warn? #9245
Comments
@metamatt Thanks. There's a simple fix, but going to investigate to make sure it's also the best. |
So, a conceptually simple fix. Working out the details. |
I hope the solution will make MakeCallback always work, as intended. Having to correctly decide between two different ways of calling javascript from C++ dependent on context is really not acceptable, as it will lead to much confusion and headache. |
@kkoopa That's the plan. :) |
Adding to the 0.12.1 milestone, as discussed during the last core team meeting. |
Will this be back-ported to 0.10? |
NAN will most likely reimplement and backport all of it, as I don't imagine 0.8 getting updated, so 0.10 will at least be covered that way. |
@trevnorris Any update on this? |
@misterdjules No, sorry. I've taken several stabs at it but every time I've been thwarted by some edge scenario. I'll take another look this week and see if anything new pops to mind. |
What is the status on this? Is it doable or should it be resolved some other way? |
@kkoopa Ooh. Just had an idea. Something like: bool in_make_callback = false;
if (!env->in_make_callback()) {
env->set_in_make_callback(true);
in_make_callback = true;
}
// perform operations 'n stuff
if (in_make_callback) {
env->set_in_make_callback(false);
} So the call can keep track of whether it's in a |
Cool. Hope it works. |
I believe this is the most appropriate way to handle exceptions. Using v8::Function::Call rather than node::MakeCallback (via NanMakeCallback) means that these functions will not work with domains, but that seems appropriate. I don't know if nodejs/node-v0.x-archive#9245 or nodejs/nan#284 should be a concern here or not.
I still haven't found a way to fix all the edge cases. The rules for calling it are pretty simple. It has to be the first entry into the JS stack. I'm going to keep thinking about it though. Feel like there's got to be a cleaner architecture here. |
Thanks for sticking with this. To reiterate why it's important, I'll link to the nan documentation:
Having two different mechanisms ("synchronously invoke JS code" from C++ code invoked synchronously, which is |
Ah yeah. That documentation is worded poorly. |
If one of you were to submit a PR with better documentation, I'd be happy to merge it, assuming this is the official approach (for the time being). |
@metamatt I have a partial fix for this issue. My final issue to resolve is the fact that the initial set of callback don't run in a |
Add a scope that will allow MakeCallback to know whether or not it's currently running. This will prevent nextTickQueue and the MicrotaskQueue from being processed recursively. It is also required to wrap the bootloading stage since it doesn't run within a MakeCallback. Ref: nodejs/node-v0.x-archive#9245 PR-URL: nodejs#4507 Reviewed-By: Fedor Indutny <[email protected]>
This may finally be fixed by nodejs/node#4507 |
Add a scope that will allow MakeCallback to know whether or not it's currently running. This will prevent nextTickQueue and the MicrotaskQueue from being processed recursively. It is also required to wrap the bootloading stage since it doesn't run within a MakeCallback. Ref: nodejs/node-v0.x-archive#9245 PR-URL: #4507 Reviewed-By: Fedor Indutny <[email protected]>
Add a scope that will allow MakeCallback to know whether or not it's currently running. This will prevent nextTickQueue and the MicrotaskQueue from being processed recursively. It is also required to wrap the bootloading stage since it doesn't run within a MakeCallback. Ref: nodejs/node-v0.x-archive#9245 PR-URL: nodejs#4507 Reviewed-By: Fedor Indutny <[email protected]>
Add a scope that will allow MakeCallback to know whether or not it's currently running. This will prevent nextTickQueue and the MicrotaskQueue from being processed recursively. It is also required to wrap the bootloading stage since it doesn't run within a MakeCallback. Ref: nodejs/node-v0.x-archive#9245 Ref: #7048 PR-URL: #4507 Reviewed-By: Fedor Indutny <[email protected]>
Add a scope that will allow MakeCallback to know whether or not it's currently running. This will prevent nextTickQueue and the MicrotaskQueue from being processed recursively. It is also required to wrap the bootloading stage since it doesn't run within a MakeCallback. Ref: nodejs/node-v0.x-archive#9245 Ref: #7048 PR-URL: #4507 Reviewed-By: Fedor Indutny <[email protected]>
Add a scope that will allow MakeCallback to know whether or not it's currently running. This will prevent nextTickQueue and the MicrotaskQueue from being processed recursively. It is also required to wrap the bootloading stage since it doesn't run within a MakeCallback. Ref: nodejs/node-v0.x-archive#9245 Ref: #7048 PR-URL: #4507 Reviewed-By: Fedor Indutny <[email protected]>
Add a scope that will allow MakeCallback to know whether or not it's currently running. This will prevent nextTickQueue and the MicrotaskQueue from being processed recursively. It is also required to wrap the bootloading stage since it doesn't run within a MakeCallback. Ref: nodejs/node-v0.x-archive#9245 Ref: #7048 PR-URL: #4507 Reviewed-By: Fedor Indutny <[email protected]>
This issue springs from TooTallNate/node-weak#35, but the root cause is that
node::MakeCallback
is dangerous if misused, and it would be nice to prevent its misuse.By "misuse", I mean: if you have a
Handle<Function>
in a node addon and you want to call it, you have the choice of calling it directly (Handle<Function>::Call()
) or vianode::MakeCallback
. You should do the former if your addon code was invoked from JS code; you should do the latter if your addon code was invoked directly from libuv as an event callback. This difference, while crucial, is not plainly obvious, and if you get it wrong, the results are really bad (preemption of Javascript code, that breaks Node's entire threadless/concurrency/consistency model).Note comment TooTallNate/node-weak#36 (comment) from @trevnorris (and the surrounding discussion) saying that MakeCallback should be benign if called unnecessarily, but in my observation, that's not true. So I'm following up on this old discussion with an issue report and demo/repro case (for NodeJS 0.12.0) that shows it's actually (and still) dangerous if called this way.
The repro case is at https://gist.github.com/metamatt/4ce96adbf14de9a97d41.
The text was updated successfully, but these errors were encountered: