Skip to content

Commit 4704e58

Browse files
committed
src: fix cleanup hook removal for InspectorTimer
Fix this to account for the fact that `Stop()` may already have been called from a cleanup hook when the `inspector::Agent` is deleted along with the `Environment`, at which point cleanup hooks are no longer available. Backport-PR-URL: #35241 PR-URL: #32523 Reviewed-By: Matheus Marchini <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 4513b6a commit 4704e58

File tree

1 file changed

+24
-16
lines changed

1 file changed

+24
-16
lines changed

src/inspector_agent.cc

+24-16
Original file line numberDiff line numberDiff line change
@@ -355,32 +355,26 @@ class InspectorTimer {
355355
int64_t interval_ms = 1000 * interval_s;
356356
uv_timer_start(&timer_, OnTimer, interval_ms, interval_ms);
357357
timer_.data = this;
358-
359-
env->AddCleanupHook(CleanupHook, this);
360358
}
361359

362360
InspectorTimer(const InspectorTimer&) = delete;
363361

364362
void Stop() {
365-
env_->RemoveCleanupHook(CleanupHook, this);
363+
if (timer_.data == nullptr) return;
366364

367-
if (timer_.data == this) {
368-
timer_.data = nullptr;
369-
uv_timer_stop(&timer_);
370-
env_->CloseHandle(reinterpret_cast<uv_handle_t*>(&timer_), TimerClosedCb);
371-
}
365+
timer_.data = nullptr;
366+
uv_timer_stop(&timer_);
367+
env_->CloseHandle(reinterpret_cast<uv_handle_t*>(&timer_), TimerClosedCb);
372368
}
373369

370+
inline Environment* env() const { return env_; }
371+
374372
private:
375373
static void OnTimer(uv_timer_t* uvtimer) {
376374
InspectorTimer* timer = node::ContainerOf(&InspectorTimer::timer_, uvtimer);
377375
timer->callback_(timer->data_);
378376
}
379377

380-
static void CleanupHook(void* data) {
381-
static_cast<InspectorTimer*>(data)->Stop();
382-
}
383-
384378
static void TimerClosedCb(uv_handle_t* uvtimer) {
385379
std::unique_ptr<InspectorTimer> timer(
386380
node::ContainerOf(&InspectorTimer::timer_,
@@ -403,16 +397,29 @@ class InspectorTimerHandle {
403397
InspectorTimerHandle(Environment* env, double interval_s,
404398
V8InspectorClient::TimerCallback callback, void* data) {
405399
timer_ = new InspectorTimer(env, interval_s, callback, data);
400+
401+
env->AddCleanupHook(CleanupHook, this);
406402
}
407403

408404
InspectorTimerHandle(const InspectorTimerHandle&) = delete;
409405

410406
~InspectorTimerHandle() {
411-
CHECK_NOT_NULL(timer_);
412-
timer_->Stop();
413-
timer_ = nullptr;
407+
Stop();
414408
}
409+
415410
private:
411+
void Stop() {
412+
if (timer_ != nullptr) {
413+
timer_->env()->RemoveCleanupHook(CleanupHook, this);
414+
timer_->Stop();
415+
}
416+
timer_ = nullptr;
417+
}
418+
419+
static void CleanupHook(void* data) {
420+
static_cast<InspectorTimerHandle*>(data)->Stop();
421+
}
422+
416423
InspectorTimer* timer_;
417424
};
418425

@@ -735,8 +742,9 @@ class NodeInspectorClient : public V8InspectorClient {
735742
bool is_main_;
736743
bool running_nested_loop_ = false;
737744
std::unique_ptr<V8Inspector> client_;
738-
std::unordered_map<int, std::unique_ptr<ChannelImpl>> channels_;
745+
// Note: ~ChannelImpl may access timers_ so timers_ has to come first.
739746
std::unordered_map<void*, InspectorTimerHandle> timers_;
747+
std::unordered_map<int, std::unique_ptr<ChannelImpl>> channels_;
740748
int next_session_id_ = 1;
741749
bool waiting_for_resume_ = false;
742750
bool waiting_for_frontend_ = false;

0 commit comments

Comments
 (0)