Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
inspector: make sure timer handles are cleaned up
It is not obvious that timer handles are cleaned up properly
when the current `Environment` exits, nor that the `Environment`
knows to keep track of the closing handles.

This change may not be necessary, because timer handles
close without non-trivial delay (i.e. at the end of the current
event loop term), and JS-based inspector sessions (which are
the only ones we can easily test) are destroyed when cleaning up,
closing the timers as a result. I don’t know what happens
for other kinds of inspector sessions, though.
  • Loading branch information
addaleax committed Feb 14, 2019
commit d4d34ae474b1216cafa0ef048397d1c37c6eca6a
29 changes: 21 additions & 8 deletions src/inspector_agent.cc
Original file line number Diff line number Diff line change
Expand Up @@ -301,22 +301,30 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel,

class InspectorTimer {
public:
InspectorTimer(uv_loop_t* loop,
InspectorTimer(Environment* env,
double interval_s,
V8InspectorClient::TimerCallback callback,
void* data) : timer_(),
void* data) : env_(env),
callback_(callback),
data_(data) {
uv_timer_init(loop, &timer_);
uv_timer_init(env->event_loop(), &timer_);
int64_t interval_ms = 1000 * interval_s;
uv_timer_start(&timer_, OnTimer, interval_ms, interval_ms);
timer_.data = this;

env->AddCleanupHook(CleanupHook, this);
}

InspectorTimer(const InspectorTimer&) = delete;

void Stop() {
uv_timer_stop(&timer_);
uv_close(reinterpret_cast<uv_handle_t*>(&timer_), TimerClosedCb);
env_->RemoveCleanupHook(CleanupHook, this);

if (timer_.data == this) {
timer_.data = nullptr;
uv_timer_stop(&timer_);
env_->CloseHandle(reinterpret_cast<uv_handle_t*>(&timer_), TimerClosedCb);
}
}

private:
Expand All @@ -325,6 +333,10 @@ class InspectorTimer {
timer->callback_(timer->data_);
}

static void CleanupHook(void* data) {
static_cast<InspectorTimer*>(data)->Stop();
}

static void TimerClosedCb(uv_handle_t* uvtimer) {
std::unique_ptr<InspectorTimer> timer(
node::ContainerOf(&InspectorTimer::timer_,
Expand All @@ -334,6 +346,7 @@ class InspectorTimer {

~InspectorTimer() {}

Environment* env_;
uv_timer_t timer_;
V8InspectorClient::TimerCallback callback_;
void* data_;
Expand All @@ -343,9 +356,9 @@ class InspectorTimer {

class InspectorTimerHandle {
public:
InspectorTimerHandle(uv_loop_t* loop, double interval_s,
InspectorTimerHandle(Environment* env, double interval_s,
V8InspectorClient::TimerCallback callback, void* data) {
timer_ = new InspectorTimer(loop, interval_s, callback, data);
timer_ = new InspectorTimer(env, interval_s, callback, data);
}

InspectorTimerHandle(const InspectorTimerHandle&) = delete;
Expand Down Expand Up @@ -540,7 +553,7 @@ class NodeInspectorClient : public V8InspectorClient {
TimerCallback callback,
void* data) override {
timers_.emplace(std::piecewise_construct, std::make_tuple(data),
std::make_tuple(env_->event_loop(), interval_s, callback,
std::make_tuple(env_, interval_s, callback,
data));
}

Expand Down