简体   繁体   中英

Access a pointer from a child thread

I have a struct that looks like this:

struct Work {
  uv_work_t requst;
  Local<Promise::Resolver> resolver;
};

I then have this method which crops an image with imagemagick:

void MagickNode::Crop(const FunctionCallbackInfo<Value> &args) {
  // Create a promise
  Local<Promise::Resolver> resolver = v8::Promise::Resolver::New(i.isolate);
  args.GetReturnValue().Set(resolver->GetPromise());

  // Create a worker
  Work *work = new Work();
  work->requst.data = work;
  work->resolver = resolver;

  // Do work
  uv_queue_work(uv_default_loop(), &work->requst, [](uv_work_t *req) {
    // Do the heavy lifting
  }, WorkVoidComplete);
}

When the process is complete, I want to resolve the promise. Which I do here:

void MagickNode::WorkVoidComplete(uv_work_t *req, int status) {
  // Setup the required items
  Isolate *isolate = Isolate::GetCurrent();
  v8::HandleScope handleScope(isolate);
  Work *work = static_cast<Work *>(req->data);

  // Resolve the promise
  work->resolver->Resolve(Undefined(isolate));
  delete work;
}

The problem, is that when work->resolver->Resolve runs it gives Segmentation fault . I think that this is because it is executed from a thread when it was created on the parent thread giving me no access.

How can I get access and run that line?

If I move that line to the end of the method MagickNode::Crop , it runs without error and the promise gets called.

Your WorkVoidComplete will actually be called in the loop thread. The problem here is that you're using a Local<T> handle instead of a Persistent<T> handle.

When the scope of MagickNode::Crop closes the local handle is released.

Changing your struct to use v8::Persistent<Promise::Resolver> will fix the problem. Note that when you're done with a persistent reference handle it must be manually released by calling Reset() .

class Work {
 public:
  Work(Isolate* i, Local<Promise::Resolver> r)
    : isolate_(i) {
      resolver_.Reset(i, r);
    }

  ~Work() {
    resolver_.Reset();
  }

  inline uv_work_t* request() { return &request_; }
  inline Isolate* isolate() { return isolate_; }
  inline Local<Promise::Resolver> resolver() {
    return resolver_.Get(isolate_);
  }

 private:
  Isolate* isolate_;
  Persistent<Promise::Resolver> resolver_;
  uv_work_t request_;
};

void Something(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Local<Context> context = isolate->GetCurrentContext();

  Local<Promise::Resolver> resolver =
    v8::Promise::Resolver::New(context).ToLocalChecked();

  Work* work = new Work(isolate, resolver);
  work->request()->data = work;
  uv_queue_work(uv_default_loop(), work->request(), DoWork, WorkComplete);

  args.GetReturnValue().Set(resolver->GetPromise());
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM