From ececdd316766998ca3309ccb01f5618d44d0d91e Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Mon, 8 Jan 2018 21:05:14 -0500 Subject: perf_hooks: fix scheduling regression Scheduling a PerformanceGCCallback should not keep the loop alive but due to the recent switch to using the native SetImmediate method, it does. Go back to using uv_async_t and add a regression test. PR-URL: https://github.com/nodejs/node/pull/18051 Fixes: https://github.com/nodejs/node/issues/18047 Refs: https://github.com/nodejs/node/pull/18020 Reviewed-By: James M Snell Reviewed-By: Anna Henningsen --- src/node_perf.cc | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'src/node_perf.cc') diff --git a/src/node_perf.cc b/src/node_perf.cc index 6a59d50fb6..97d3a2d995 100644 --- a/src/node_perf.cc +++ b/src/node_perf.cc @@ -182,8 +182,9 @@ void SetupPerformanceObservers(const FunctionCallbackInfo& args) { } // Creates a GC Performance Entry and passes it to observers -void PerformanceGCCallback(Environment* env, void* ptr) { - GCPerformanceEntry* entry = static_cast(ptr); +void PerformanceGCCallback(uv_async_t* handle) { + GCPerformanceEntry* entry = static_cast(handle->data); + Environment* env = entry->env(); HandleScope scope(env->isolate()); Local context = env->context(); @@ -200,6 +201,10 @@ void PerformanceGCCallback(Environment* env, void* ptr) { } delete entry; + auto closeCB = [](uv_handle_t* handle) { + delete reinterpret_cast(handle); + }; + uv_close(reinterpret_cast(handle), closeCB); } // Marks the start of a GC cycle @@ -216,11 +221,16 @@ void MarkGarbageCollectionEnd(Isolate* isolate, v8::GCCallbackFlags flags, void* data) { Environment* env = static_cast(data); - env->SetImmediate(PerformanceGCCallback, - new GCPerformanceEntry(env, - static_cast(type), - performance_last_gc_start_mark_, - PERFORMANCE_NOW())); + uv_async_t* async = new uv_async_t(); + if (uv_async_init(env->event_loop(), async, PerformanceGCCallback)) + return delete async; + uv_unref(reinterpret_cast(async)); + async->data = + new GCPerformanceEntry(env, + static_cast(type), + performance_last_gc_start_mark_, + PERFORMANCE_NOW()); + CHECK_EQ(0, uv_async_send(async)); } -- cgit v1.2.3