Always remove all the DNS sockets on an c-ares event

Because c-ares may close one of its socket, even if it’s not the one that
has the event. Otherwise we may not know when a socket has been removed from
our poller (automatically, when close()ed) and this leads to bugs.
This commit is contained in:
louiz’
2016-07-28 10:34:01 +02:00
parent de0eff6e94
commit 11a1c0cc99
4 changed files with 26 additions and 5 deletions
+10 -1
View File
@@ -37,6 +37,7 @@ ares_channel& DNSHandler::get_channel()
void DNSHandler::destroy() void DNSHandler::destroy()
{ {
this->remove_all_sockets_from_poller();
this->socket_handlers.clear(); this->socket_handlers.clear();
::ares_destroy(this->channel); ::ares_destroy(this->channel);
::ares_library_cleanup(); ::ares_library_cleanup();
@@ -95,7 +96,7 @@ void DNSHandler::watch_dns_sockets(std::shared_ptr<Poller>& poller)
if (it == this->socket_handlers.end()) if (it == this->socket_handlers.end())
{ {
this->socket_handlers.emplace(this->socket_handlers.begin(), this->socket_handlers.emplace(this->socket_handlers.begin(),
std::make_unique<DNSSocketHandler>(poller, i)); std::make_unique<DNSSocketHandler>(poller, *this, i));
it = this->socket_handlers.begin(); it = this->socket_handlers.begin();
} }
poller->add_socket_handler(it->get()); poller->add_socket_handler(it->get());
@@ -122,4 +123,12 @@ void DNSHandler::watch_dns_sockets(std::shared_ptr<Poller>& poller)
} }
} }
void DNSHandler::remove_all_sockets_from_poller()
{
for (const auto& socket_handler: this->socket_handlers)
{
socket_handler->remove_from_poller();
}
}
#endif /* CARES_FOUND */ #endif /* CARES_FOUND */
+1
View File
@@ -40,6 +40,7 @@ public:
* and library. * and library.
*/ */
void destroy(); void destroy();
void remove_all_sockets_from_poller();
ares_channel& get_channel(); ares_channel& get_channel();
static DNSHandler instance; static DNSHandler instance;
+10 -3
View File
@@ -8,8 +8,10 @@
#include <ares.h> #include <ares.h>
DNSSocketHandler::DNSSocketHandler(std::shared_ptr<Poller> poller, DNSSocketHandler::DNSSocketHandler(std::shared_ptr<Poller> poller,
DNSHandler& handler,
const socket_t socket): const socket_t socket):
SocketHandler(poller, socket) SocketHandler(poller, socket),
handler(handler)
{ {
} }
@@ -21,7 +23,7 @@ void DNSSocketHandler::on_recv()
{ {
// always stop watching send and read events. We will re-watch them if the // always stop watching send and read events. We will re-watch them if the
// next call to ares_fds tell us to // next call to ares_fds tell us to
this->poller->remove_socket_handler(this->socket); this->handler.remove_all_sockets_from_poller();
::ares_process_fd(DNSHandler::instance.get_channel(), this->socket, ARES_SOCKET_BAD); ::ares_process_fd(DNSHandler::instance.get_channel(), this->socket, ARES_SOCKET_BAD);
} }
@@ -29,7 +31,7 @@ void DNSSocketHandler::on_send()
{ {
// always stop watching send and read events. We will re-watch them if the // always stop watching send and read events. We will re-watch them if the
// next call to ares_fds tell us to // next call to ares_fds tell us to
this->poller->remove_socket_handler(this->socket); this->handler.remove_all_sockets_from_poller();
::ares_process_fd(DNSHandler::instance.get_channel(), ARES_SOCKET_BAD, this->socket); ::ares_process_fd(DNSHandler::instance.get_channel(), ARES_SOCKET_BAD, this->socket);
} }
@@ -38,4 +40,9 @@ bool DNSSocketHandler::is_connected() const
return true; return true;
} }
void DNSSocketHandler::remove_from_poller()
{
this->poller->remove_socket_handler(this->socket);
}
#endif /* CARES_FOUND */ #endif /* CARES_FOUND */
+5 -1
View File
@@ -13,10 +13,12 @@
* (Poller reported it to be writable or readeable) * (Poller reported it to be writable or readeable)
*/ */
class DNSHandler;
class DNSSocketHandler: public SocketHandler class DNSSocketHandler: public SocketHandler
{ {
public: public:
explicit DNSSocketHandler(std::shared_ptr<Poller> poller, const socket_t socket); explicit DNSSocketHandler(std::shared_ptr<Poller> poller, DNSHandler& handler, const socket_t socket);
~DNSSocketHandler() = default; ~DNSSocketHandler() = default;
DNSSocketHandler(const DNSSocketHandler&) = delete; DNSSocketHandler(const DNSSocketHandler&) = delete;
DNSSocketHandler(DNSSocketHandler&&) = delete; DNSSocketHandler(DNSSocketHandler&&) = delete;
@@ -38,8 +40,10 @@ public:
* Always true, see the comment for connect() * Always true, see the comment for connect()
*/ */
bool is_connected() const override final; bool is_connected() const override final;
void remove_from_poller();
private: private:
DNSHandler& handler;
}; };
#endif // CARES_FOUND #endif // CARES_FOUND