1#include <node.h> 2#include <uv.h> 3#include <assert.h> 4 5void MustNotCall(void* arg, void(*cb)(void*), void* cbarg) { 6 assert(0); 7} 8 9struct AsyncData { 10 uv_async_t async; 11 v8::Isolate* isolate; 12 node::AsyncCleanupHookHandle handle; 13 void (*done_cb)(void*); 14 void* done_arg; 15}; 16 17void AsyncCleanupHook(void* arg, void(*cb)(void*), void* cbarg) { 18 AsyncData* data = static_cast<AsyncData*>(arg); 19 uv_loop_t* loop = node::GetCurrentEventLoop(data->isolate); 20 assert(loop != nullptr); 21 int err = uv_async_init(loop, &data->async, [](uv_async_t* async) { 22 AsyncData* data = static_cast<AsyncData*>(async->data); 23 // Attempting to remove the cleanup hook here should be a no-op since it 24 // has already been started. 25 node::RemoveEnvironmentCleanupHook(std::move(data->handle)); 26 27 uv_close(reinterpret_cast<uv_handle_t*>(async), [](uv_handle_t* handle) { 28 AsyncData* data = static_cast<AsyncData*>(handle->data); 29 data->done_cb(data->done_arg); 30 delete data; 31 }); 32 }); 33 assert(err == 0); 34 35 data->async.data = data; 36 data->done_cb = cb; 37 data->done_arg = cbarg; 38 uv_async_send(&data->async); 39} 40 41void Initialize(v8::Local<v8::Object> exports, 42 v8::Local<v8::Value> module, 43 v8::Local<v8::Context> context) { 44 AsyncData* data = new AsyncData(); 45 data->isolate = context->GetIsolate(); 46 auto handle = node::AddEnvironmentCleanupHook( 47 context->GetIsolate(), 48 AsyncCleanupHook, 49 data); 50 data->handle = std::move(handle); 51 52 auto must_not_call_handle = node::AddEnvironmentCleanupHook( 53 context->GetIsolate(), 54 MustNotCall, 55 nullptr); 56 node::RemoveEnvironmentCleanupHook(std::move(must_not_call_handle)); 57} 58 59NODE_MODULE_CONTEXT_AWARE(NODE_GYP_MODULE_NAME, Initialize) 60