Skip to content

Instantly share code, notes, and snippets.

@OrangeDog
Last active December 19, 2015 14:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OrangeDog/6e37909d3683fa999707 to your computer and use it in GitHub Desktop.
Save OrangeDog/6e37909d3683fa999707 to your computer and use it in GitHub Desktop.
uv_work and MakeCallback segfault
Program received signal SIGSEGV, Segmentation fault.
0x00000000007b9a07 in v8::internal::JSReceiver::Lookup(v8::internal::String*, v8::internal::LookupResult*) ()
(gdb) bt
#0 0x00000000007b9a07 in v8::internal::JSReceiver::Lookup(v8::internal::String*, v8::internal::LookupResult*) ()
#1 0x00000000007bc11a in v8::internal::Object::GetPropertyWithReceiver(v8::internal::Object*, v8::internal::String*, PropertyAttributes*) ()
#2 0x000000000081e0d4 in v8::internal::Runtime::GetObjectProperty(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>) ()
#3 0x000000000071152f in v8::internal::GetProperty(v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>) ()
#4 0x00000000006aff57 in v8::Object::Get(v8::Handle<v8::Value>) ()
#5 0x000000000057c152 in node::MakeCallback(v8::Handle<v8::Object>, v8::Handle<v8::Function>, int, v8::Handle<v8::Value>*) ()
#6 0x00007ffff67b608c in (anonymous namespace)::run_callback (req=0xdfed60) at ../src/nodejs.cpp:154
#7 0x00000000005cd91e in ?? ()
#8 0x00000000005c3aa2 in ?? ()
#9 0x00000000005c53b5 in eio_poll ()
#10 0x00000000005d53d8 in ?? ()
#11 0x00000000005c2891 in ?? ()
#12 0x00000000005c7002 in ev_invoke_pending ()
#13 0x00000000005c2f1f in ?? ()
#14 0x00000000005c31a0 in uv_run ()
#15 0x000000000057da87 in node::Start(int, char**) ()
struct run_baton {
run_baton() {
isolate = Isolate::GetCurrent();
global = Persistent<Object>(Context::GetCurrent()->Global());
};
uv_work_t req;
Isolate* isolate;
Handle<Object> global;
Handle<Function> callbackFn;
std::string result;
std::string errString;
}
void run_callback(uv_work_t *req) {
run_baton *baton = reinterpret_cast<run_baton*>(req->data);
Locker lock(baton->isolate);
Isolate::Scope iscope(baton->isolate);
HandleScope scope;
Handle<Value> args[2];
if (!baton->errString.empty()) {
args[0] = Exception::Error(String::New(baton->errString.c_str()));
args[1] = Undefined();
}
else {
args[0] = Undefined();
args[1] = String::New(baton->result.c_str());
}
baton->global->Get(String::NewSymbol("domain")); // was here for debugging, but made it stop segfaulting in some cases
node::MakeCallback(baton->global, baton->callbackFn, 2, args);
// this doesn't segfault, but also doesn't direct excptions to the bound domain
//baton->callbackFn->Call(baton->global, 2, args);
delete baton;
}
Handle<Value> Run(const Arguments& args) {
HandleScope scope;
run_baton* baton = new run_baton();
baton->req.data = reinterpret_cast<void*>(baton);
baton->callbackFn = Persistent<Function>::New(Handle<Function>::Cast(args[1]));
uv_queue_work(uv_default_loop(), &baton->req, run_work, run_callback);
return scope.Close(Local<Value>());
}
@trevnorris
Copy link

This works on v0.10. Though I'm landing a patch that will allow you to support domains using MakeCallback this way. Was an oversight on my part.

#include <v8.h>
#include <node.h>

using namespace v8;

struct run_baton {
  uv_work_t req;
  Persistent<Function> callbackFn;
};


void run_work(uv_work_t* req) { }


void run_callback(uv_work_t* req, int status) {
  HandleScope scope;

  run_baton* baton = static_cast<run_baton*>(req->data);

  node::MakeCallback(Context::GetCurrent()->Global(),
                     baton->callbackFn,
                     0,
                     NULL);

  // need to properly cleanup you're Persistent as well
  baton->callbackFn.Dispose();
  baton->callbackFn.Clear();
  delete baton;
}


Handle<Value> Run(const Arguments& args) {
  HandleScope scope;

  assert(args[0]->IsFunction());

  run_baton* baton = new run_baton;
  baton->req.data = static_cast<void*>(baton);
  baton->callbackFn = Persistent<Function>::New(args[0].As<Function>());

  uv_queue_work(uv_default_loop(), &baton->req, run_work, run_callback);

  return Undefined();
}


void Init(Handle<Object> target) {
  HandleScope scope;

  target->Set(String::New("run"),
      FunctionTemplate::New(Run)->GetFunction());
}


NODE_MODULE(basics, Init)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment