2014년 12월 13일 토요일

Native add-on help (segfaults w/ HandleScope)

I am creating a linux shared object (.so) from an existing binary tool written in C, writing a custom C++ v8 bound native add on which links to the shared object.

Everything so far is working swimmingly, node-gyp compiles, links & provides the module. The primary functionality is in place and also works fine until I attempt to do the following:

From the existing C functionality compiled as ...
extern "C" { /* ... */ }

I pass a struct & additional data to another function (also wrapped with the extern) which passes that same data to a C++ function (member of a class) at which time the call to
HandleScoope scope;
causes a segfault.

#include <node.h>
#include <v8.h>
 
using namespace node;
using namespace v8;
 
/* This function 'ReturnObject' is
 * called from an existing library
 * written in C
*/

extern "C" {
  
void ReturnObject() {
    classname cn
;

    cn
.Report();
  
}
}
 
void classname::Report() {
  
HandleScope scope; // Here is where I am getting segfaults
  classname cn
;

  
Local<Object> obj = Object::New();
  v8
::Persistent<v8::Object> pobj(v8::Persistent<v8::Object>::New(obj));

  cn
.RunCallback(pobj);
} 

My assumption is that when I call HandleScope from the extern wrapped function is that the scope is missing. My other assumption is that I cannot do this from a child process, which is what I believe the problem is.

Any tips or pointers on how I can accomplish this is appreciated.



Not knowing much about your existing C functionnality, I would assume you are calling V8 methods (scope) from the wrong thread. It is very much possible that the library you are binding to uses threads.
The rule of thumb is not to call any V8 function from any other thread than the one running the main uv_loop.

So, the best thing to do in your ReturnObject() function is to push some work in the uv_queue or whatever that's called now. Your work will get called next time the uv_loop runs, and you'll be in the right thread.



I had to use the uv_async_init(), uv_async_send() a persistent callback and uv_async_close() to wake up the main thread and perform the callback when the scope was back on the parent thread. Thanks!



Glad it worked despite my less-than-clear indications =)


댓글 없음:

댓글 쓰기