Using MakeCallback for domain-based error propagation and setting recv

68 views
Skip to first unread message

Jeff Waller

unread,
Jul 14, 2015, 9:03:21 PM7/14/15
to nod...@googlegroups.com
When dispatching from an asynchronous operation using C++, the function node::MakeCallback is
supposed to automatically set the domain of the callback. So if method throws, then an event will
be sent to the domain.  At least that's the expectation.  From the node source, it appears that recv
is used to obtain the domain to which these events will posted

NODE_EXTERN v8::Handle<v8::Value> MakeCallback(

    v8::Isolate* isolate,

    v8::Handle<v8::Object> recv,

    const char* method,

    int argc,

    v8::Handle<v8::Value>* argv);




Local<Context> context = recv->CreationContext();
Environment* env = Environment::GetCurrent(context);

and then later

if (env->using_domains())

etc.

What recv is and how's it's derived  is a mystery.  I can't find it documented.  I've tried 
various values for recv:  args.This(), Context()->Global(), the callback itself, etc. saved directly
as a Persistent or saved as a object contained in a Persistent Array... all approaches fail. So
here I am.  If anyone knows what this object is or can suggest a next step, thanks in advance.



Ben Noordhuis

unread,
Jul 15, 2015, 7:54:20 AM7/15/15
to nod...@googlegroups.com
|recv| is the receiver object, the value of the |this| object inside
the function call.

If your code looks like this:

var addon = require('/path/to/addon.node');
var callback = function() { /* ... */ };
addon.makeCallback(callback);

Then args.This() equals |addon|, the native module object, and won't
normally have the .domain property that MakeCallback() looks for.

You can pass in the receiver explicitly and pass it on to MakeCallback:

var recv = { domain: process.domain, /* ... */ };
addon.makeCallback(recv, callback);

Or if you want |recv| to show up as args.This():

addon.makeCallback.call(recv, callback);

Jeff Waller

unread,
Jul 15, 2015, 10:39:22 PM7/15/15
to nod...@googlegroups.com
Then args.This() equals |addon|, the native module object, and won't
normally have the .domain property that MakeCallback() looks for.

Much thanks, that clarifies.

I have a followup question. There are multiple functions my
addon exposes that are of this form, and I think I can change
all of them to behave this new way.

However, there are in addition some endpoints that return an object
that itself exposes such an asynchronous mechanism, and in
that case, I think args.This() will point to the object and can't
be replaced, and can't really be used directly either because
then the domain would be bound to when that object was created
and not when the function was called.  Does that sound about
right?  Is that a typical problem?

Ben Noordhuis

unread,
Jul 16, 2015, 8:37:29 AM7/16/15
to nod...@googlegroups.com
I think so. I'd probably query process.domain /
require('domain').active at the time of the function call.
Reply all
Reply to author
Forward
0 new messages