nodejs / nodejs/nan

Persistant callback not working

Open
#854 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
3.4k
Forks
531
Avg merge
21m
Merged PRs (30d)
1

Description

In my c++ library I have the following:

typedef void (update_callback)(LibClass *data);
void setCallback(update_callback *callback) {
  this->callback = callback;
}

Using nan, I am assigning the persistent function to be called from js using a setUpdateCallback function e.g.:

myClass.setUpdateCallback(function() { console.log("Hello"); })

setUpdateCallback calls this nan function:

void MyClass::SetUpdateCallback(const Nan::FunctionCallbackInfo<v8::Value>& info) {

  // get the object
  MyClass *obj = ObjectWrap::Unwrap<MyClass>(info.Holder());

  // I have tried a million combinations, this one is the latest try
  v8::Isolate *isolate = v8::Isolate::GetCurrent();
  v8::Handle<v8::Function> callback = v8::Handle<v8::Function>::Cast(info[0]);
  v8::Persistent<v8::Function> callback_persistent(isolate, callback);
  obj->cb = callback_persistent;

  // assign the callback, lib here is the custom class that the Nan::ObjectWrap contains as a variable
  obj->lib->setCallback(MyClass::Update);

  // return the class, this can be ommited
  info.GetReturnValue().Set(info.This());

}

And the MyClass::Update does the followng:

void MyClass::Update(LibClass *libClass) {

  // get the obj related to the current LibClass
  // libs here is a map with pair<LibClass *, MyClass *>
  MyClass *parent = libs.at(libClass);

  // create callback
  v8::Isolate *isolate = v8::Isolate::GetCurrent();
  v8::HandleScope scope(isolate);
  v8::Local<v8::Function> callback = v8::Local<v8::Function>::New(isolate, parent->cb);

  Nan::Call(callback, Nan::GetCurrentContext()->Global(), 0, NULL);
  // calling the callback twice works successfully
  Nan::Call(callback, Nan::GetCurrentContext()->Global(), 0, NULL);

}

The libClass does not produce a callback, MyClass should set the callback function to call, and throughout the program's execution, libClass will call the update function at random times based on some data.

So what I want to do is to set that callback function in javascript and be able to call it whenever I want from the libClass but it never works. It works on initialization and after that it seems that it is being called by the garbage collector even though it's a persistent function.

I am new to both C++ and Nan and none of the solutions found on the internet were helpful, they were all implementations of callbacks, so am I missing something ?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with SetUpdateCallback and MyClass::Update in the issue, then review how the persistent V8 callback is stored and invoked through Nan. Reproduce the JavaScript setUpdateCallback example and the later libClass updates, checking whether the callback remains valid when invoked at random times. Done means the callback reliably runs after initialization without garbage-collection failures.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, node.js
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.