From f47adfbda5c06263a78c0c74a705b0d5d3cd2944 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Mon, 18 Mar 2019 23:14:49 +0800 Subject: [PATCH] src: fix DTrace GC callbacks DCHECKs and add cleanup Use the variant of GC callbacks that takes data to avoid running into DCHECKs when multiple Environments try to add the same callback to the same isolate multiple times. In addition, remove the callbacks in the Environment cleanup hook. PR-URL: https://github.com/nodejs/node/pull/26742 Fixes: https://github.com/nodejs/node/issues/26736 Reviewed-By: Matheus Marchini Reviewed-By: Anna Henningsen Reviewed-By: James M Snell --- src/node_dtrace.cc | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/node_dtrace.cc b/src/node_dtrace.cc index 5b2b9b8e14e942..910c19df73c7ef 100644 --- a/src/node_dtrace.cc +++ b/src/node_dtrace.cc @@ -248,15 +248,19 @@ void DTRACE_HTTP_CLIENT_RESPONSE(const FunctionCallbackInfo& args) { NODE_HTTP_CLIENT_RESPONSE(&conn, conn.remote, conn.port, conn.fd); } - -void dtrace_gc_start(Isolate* isolate, GCType type, GCCallbackFlags flags) { +void dtrace_gc_start(Isolate* isolate, + GCType type, + GCCallbackFlags flags, + void* data) { // Previous versions of this probe point only logged type and flags. // That's why for reasons of backwards compatibility the isolate goes last. NODE_GC_START(type, flags, isolate); } - -void dtrace_gc_done(Isolate* isolate, GCType type, GCCallbackFlags flags) { +void dtrace_gc_done(Isolate* isolate, + GCType type, + GCCallbackFlags flags, + void* data) { // Previous versions of this probe point only logged type and flags. // That's why for reasons of backwards compatibility the isolate goes last. NODE_GC_DONE(type, flags, isolate); @@ -272,8 +276,16 @@ void InitDTrace(Environment* env) { } #endif - env->isolate()->AddGCPrologueCallback(dtrace_gc_start); - env->isolate()->AddGCEpilogueCallback(dtrace_gc_done); + // We need to use the variant of GC callbacks that takes data to + // avoid running into DCHECKs when multiple Environments try to add + // the same callback to the same isolate multiple times. + env->isolate()->AddGCPrologueCallback(dtrace_gc_start, env); + env->isolate()->AddGCEpilogueCallback(dtrace_gc_done, env); + env->AddCleanupHook([](void* data) { + Environment* env = static_cast(data); + env->isolate()->RemoveGCPrologueCallback(dtrace_gc_start, env); + env->isolate()->RemoveGCEpilogueCallback(dtrace_gc_done, env); + }, env); } void InitializeDTrace(Local target,