Skip to content

Commit e7ac5bc

Browse files
committed
Guard against collecting async ID while performing GC
1 parent 89afc6d commit e7ac5bc

File tree

2 files changed

+48
-3
lines changed

2 files changed

+48
-3
lines changed

bindings/profilers/wall.cc

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -315,9 +315,7 @@ void SignalHandler::HandleProfilerSignal(int sig,
315315
auto time_from = Now();
316316
old_handler(sig, info, context);
317317
auto time_to = Now();
318-
int64_t async_id = -1;
319-
// don't capture for now until we work out the issues with GC and thread start
320-
// static_cast<int64_t>(node::AsyncHooksGetExecutionAsyncId(isolate));
318+
auto async_id = prof->GetAsyncId(isolate);
321319
prof->PushContext(time_from, time_to, cpu_time, async_id);
322320
}
323321
#else
@@ -492,6 +490,20 @@ std::shared_ptr<ContextsByNode> WallProfiler::GetContextsByNode(
492490
return contextsByNode;
493491
}
494492

493+
void GCPrologueCallback(Isolate* isolate,
494+
GCType type,
495+
GCCallbackFlags flags,
496+
void* data) {
497+
static_cast<WallProfiler*>(data)->OnGCStart(isolate);
498+
}
499+
500+
void GCEpilogueCallback(Isolate* isolate,
501+
GCType type,
502+
GCCallbackFlags flags,
503+
void* data) {
504+
static_cast<WallProfiler*>(data)->OnGCEnd();
505+
}
506+
495507
WallProfiler::WallProfiler(std::chrono::microseconds samplingPeriod,
496508
std::chrono::microseconds duration,
497509
bool includeLines,
@@ -517,6 +529,7 @@ WallProfiler::WallProfiler(std::chrono::microseconds samplingPeriod,
517529
curContext_.store(&context1_, std::memory_order_relaxed);
518530
collectionMode_.store(CollectionMode::kNoCollect, std::memory_order_relaxed);
519531

532+
// TODO: bind to this isolate? Would fix the Dispose(nullptr) issue.
520533
auto isolate = v8::Isolate::GetCurrent();
521534
v8::Local<v8::ArrayBuffer> buffer =
522535
v8::ArrayBuffer::New(isolate, sizeof(uint32_t) * kFieldCount);
@@ -526,6 +539,10 @@ WallProfiler::WallProfiler(std::chrono::microseconds samplingPeriod,
526539
fields_ = static_cast<uint32_t*>(buffer->GetBackingStore()->Data());
527540
jsArray_ = v8::Global<v8::Uint32Array>(isolate, jsArray);
528541
std::fill(fields_, fields_ + kFieldCount, 0);
542+
543+
gcCount = 0;
544+
isolate->AddGCPrologueCallback(&GCPrologueCallback, this);
545+
isolate->AddGCEpilogueCallback(&GCEpilogueCallback, this);
529546
}
530547

531548
WallProfiler::~WallProfiler() {
@@ -538,6 +555,11 @@ void WallProfiler::Dispose(Isolate* isolate) {
538555
cpuProfiler_ = nullptr;
539556

540557
g_profilers.RemoveProfiler(isolate, this);
558+
559+
if (isolate != nullptr) {
560+
isolate->RemoveGCPrologueCallback(&GCPrologueCallback, this);
561+
isolate->RemoveGCEpilogueCallback(&GCEpilogueCallback, this);
562+
}
541563
}
542564
}
543565

bindings/profilers/wall.hh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ class WallProfiler : public Nan::ObjectWrap {
5858
ContextPtr context2_;
5959
std::atomic<ContextPtr*> curContext_;
6060

61+
std::atomic<int> gcCount = 0;
62+
int64_t gcAsyncId;
63+
6164
std::atomic<CollectionMode> collectionMode_;
6265
std::atomic<uint64_t> noCollectCallCount_;
6366
std::string profileId_;
@@ -149,6 +152,26 @@ class WallProfiler : public Nan::ObjectWrap {
149152
return threadCpuStopWatch_.GetAndReset();
150153
}
151154

155+
int64_t GetAsyncId(v8::Isolate* isolate) const {
156+
if (gcCount > 0) {
157+
return gcAsyncId;
158+
}
159+
return static_cast<int64_t>(node::AsyncHooksGetExecutionAsyncId(isolate));
160+
}
161+
162+
void OnGCStart(v8::Isolate* isolate) {
163+
if (gcCount++ == 0) {
164+
gcAsyncId =
165+
static_cast<int64_t>(node::AsyncHooksGetExecutionAsyncId(isolate));
166+
}
167+
}
168+
169+
void OnGCEnd() {
170+
if (--gcCount == 0) {
171+
gcAsyncId = -1;
172+
}
173+
}
174+
152175
static NAN_METHOD(New) GENERAL_REGS_ONLY;
153176
static NAN_METHOD(Start);
154177
static NAN_METHOD(Stop);

0 commit comments

Comments
 (0)