From bd04b28b9e334ac0b32695d34439b3e7af55748f Mon Sep 17 00:00:00 2001 From: Benjamin Sergeant Date: Fri, 14 Dec 2018 17:49:42 -0800 Subject: [PATCH] async dns lookup fix --- ixwebsocket/IXDNSLookup.cpp | 34 ++++++++++++++++++++++++++++++---- ixwebsocket/IXDNSLookup.h | 8 +++++++- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/ixwebsocket/IXDNSLookup.cpp b/ixwebsocket/IXDNSLookup.cpp index 70b4cfeb..6484a2a3 100644 --- a/ixwebsocket/IXDNSLookup.cpp +++ b/ixwebsocket/IXDNSLookup.cpp @@ -18,19 +18,26 @@ namespace ix const int64_t DNSLookup::kDefaultTimeout = 60 * 1000; // ms const int64_t DNSLookup::kDefaultWait = 10; // ms + std::atomic DNSLookup::_nextId(0); + std::set DNSLookup::_activeJobs; + std::mutex DNSLookup::_activeJobsMutex; + DNSLookup::DNSLookup(const std::string& hostname, int port, int wait) : _hostname(hostname), _port(port), _res(nullptr), _done(false), - _wait(wait) + _wait(wait), + _id(_nextId++) { } DNSLookup::~DNSLookup() { - ; + // Remove this job from the active jobs list + std::unique_lock lock(_activeJobsMutex); + _activeJobs.erase(_id); } struct addrinfo* DNSLookup::getAddrInfo(const std::string& hostname, @@ -92,6 +99,12 @@ namespace ix // if you need a second lookup. } + // Record job in the active Job set + { + std::unique_lock lock(_activeJobsMutex); + _activeJobs.insert(_id); + } + // // Good resource on thread forced termination // https://www.bo-yang.net/2017/11/19/cpp-kill-detached-thread @@ -100,7 +113,7 @@ namespace ix _thread.detach(); int64_t timeout = kDefaultTimeout; - std::unique_lock lock(_mutex); + std::unique_lock lock(_conditionVariableMutex); while (!_done) { @@ -140,7 +153,20 @@ namespace ix void DNSLookup::run() { - _res = getAddrInfo(_hostname, _port, _errMsg); + uint64_t id = _id; + std::string errMsg; + _res = getAddrInfo(_hostname, _port, errMsg); + + // if this isn't an active job, and the control thread is gone + // there is not thing to do, and we don't want to touch the defunct + // object data structure such as _errMsg or _condition + std::unique_lock lock(_activeJobsMutex); + if (_activeJobs.count(id) == 0) + { + return; + } + + _errMsg = errMsg; _condition.notify_one(); _done = true; } diff --git a/ixwebsocket/IXDNSLookup.h b/ixwebsocket/IXDNSLookup.h index a3d072ae..dd4f5b60 100644 --- a/ixwebsocket/IXDNSLookup.h +++ b/ixwebsocket/IXDNSLookup.h @@ -16,6 +16,7 @@ #include #include #include +#include struct addrinfo; @@ -53,7 +54,12 @@ namespace ix std::atomic _done; std::thread _thread; std::condition_variable _condition; - std::mutex _mutex; + std::mutex _conditionVariableMutex; + + std::atomic _id; + static std::atomic _nextId; + static std::set _activeJobs; + static std::mutex _activeJobsMutex; const static int64_t kDefaultTimeout; const static int64_t kDefaultWait;