src: do not persist timer handle in cares_wrap

Instead of relying on garbage collection to close the timer handle,
manage its state more explicitly.

PR-URL: https://github.com/nodejs/node/pull/21093
Fixes: https://github.com/nodejs/node/issues/18190
Refs: https://github.com/nodejs/node/pull/18307
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
This commit is contained in:
Anatoli Papirovski 2018-06-06 16:29:30 -04:00
parent 641d4a4159
commit d6bdfacf6c
No known key found for this signature in database
GPG Key ID: 614E2E1ABEB4B2C0

View File

@ -151,7 +151,8 @@ class ChannelWrap : public AsyncWrap {
void Setup(); void Setup();
void EnsureServers(); void EnsureServers();
void CleanupTimer(); void StartTimer();
void CloseTimer();
void ModifyActivityQueryCount(int count); void ModifyActivityQueryCount(int count);
@ -313,13 +314,7 @@ void ares_sockstate_cb(void* data,
if (read || write) { if (read || write) {
if (!task) { if (!task) {
/* New socket */ /* New socket */
channel->StartTimer();
/* If this is the first socket then start the timer. */
uv_timer_t* timer_handle = channel->timer_handle();
if (!uv_is_active(reinterpret_cast<uv_handle_t*>(timer_handle))) {
CHECK(channel->task_list()->empty());
uv_timer_start(timer_handle, ChannelWrap::AresTimeout, 1000, 1000);
}
task = ares_task_create(channel, sock); task = ares_task_create(channel, sock);
if (task == nullptr) { if (task == nullptr) {
@ -349,7 +344,7 @@ void ares_sockstate_cb(void* data,
channel->env()->CloseHandle(&task->poll_watcher, ares_poll_close_cb); channel->env()->CloseHandle(&task->poll_watcher, ares_poll_close_cb);
if (channel->task_list()->empty()) { if (channel->task_list()->empty()) {
uv_timer_stop(channel->timer_handle()); channel->CloseTimer();
} }
} }
} }
@ -490,15 +485,26 @@ void ChannelWrap::Setup() {
} }
library_inited_ = true; library_inited_ = true;
}
/* Initialize the timeout timer. The timer won't be started until the */ void ChannelWrap::StartTimer() {
/* first socket is opened. */ if (timer_handle_ == nullptr) {
CleanupTimer();
timer_handle_ = new uv_timer_t(); timer_handle_ = new uv_timer_t();
timer_handle_->data = static_cast<void*>(this); timer_handle_->data = static_cast<void*>(this);
uv_timer_init(env()->event_loop(), timer_handle_); uv_timer_init(env()->event_loop(), timer_handle_);
} else if (uv_is_active(reinterpret_cast<uv_handle_t*>(timer_handle_))) {
return;
}
uv_timer_start(timer_handle_, AresTimeout, 1000, 1000);
} }
void ChannelWrap::CloseTimer() {
if (timer_handle_ == nullptr)
return;
env()->CloseHandle(timer_handle_, [](uv_timer_t* handle) { delete handle; });
timer_handle_ = nullptr;
}
ChannelWrap::~ChannelWrap() { ChannelWrap::~ChannelWrap() {
if (library_inited_) { if (library_inited_) {
@ -508,17 +514,10 @@ ChannelWrap::~ChannelWrap() {
} }
ares_destroy(channel_); ares_destroy(channel_);
CleanupTimer(); CloseTimer();
} }
void ChannelWrap::CleanupTimer() {
if (timer_handle_ == nullptr) return;
env()->CloseHandle(timer_handle_, [](uv_timer_t* handle) { delete handle; });
timer_handle_ = nullptr;
}
void ChannelWrap::ModifyActivityQueryCount(int count) { void ChannelWrap::ModifyActivityQueryCount(int count) {
active_query_count_ += count; active_query_count_ += count;
if (active_query_count_ < 0) active_query_count_ = 0; if (active_query_count_ < 0) active_query_count_ = 0;
@ -566,6 +565,7 @@ void ChannelWrap::EnsureServers() {
/* destroy channel and reset channel */ /* destroy channel and reset channel */
ares_destroy(channel_); ares_destroy(channel_);
CloseTimer();
Setup(); Setup();
} }