diff options
Diffstat (limited to 'rtc_base/async_resolver.cc')
-rw-r--r-- | rtc_base/async_resolver.cc | 61 |
1 files changed, 49 insertions, 12 deletions
diff --git a/rtc_base/async_resolver.cc b/rtc_base/async_resolver.cc index 198b4984e5..d482b4e681 100644 --- a/rtc_base/async_resolver.cc +++ b/rtc_base/async_resolver.cc @@ -10,9 +10,14 @@ #include "rtc_base/async_resolver.h" +#include <memory> #include <string> #include <utility> +#include "api/ref_counted_base.h" +#include "rtc_base/synchronization/mutex.h" +#include "rtc_base/thread_annotations.h" + #if defined(WEBRTC_WIN) #include <ws2spi.h> #include <ws2tcpip.h> @@ -30,6 +35,7 @@ #include "api/task_queue/task_queue_base.h" #include "rtc_base/ip_address.h" #include "rtc_base/logging.h" +#include "rtc_base/platform_thread.h" #include "rtc_base/task_queue.h" #include "rtc_base/task_utils/to_queued_task.h" #include "rtc_base/third_party/sigslot/sigslot.h" // for signal_with_thread... @@ -87,30 +93,61 @@ int ResolveHostname(const std::string& hostname, #endif // !__native_client__ } -AsyncResolver::AsyncResolver() : error_(-1) {} +struct AsyncResolver::State : public RefCountedBase { + webrtc::Mutex mutex; + enum class Status { + kLive, + kDead + } status RTC_GUARDED_BY(mutex) = Status::kLive; +}; + +AsyncResolver::AsyncResolver() : error_(-1), state_(new State) {} AsyncResolver::~AsyncResolver() { RTC_DCHECK_RUN_ON(&sequence_checker_); + + // Ensure the thread isn't using a stale reference to the current task queue, + // or calling into ResolveDone post destruction. + webrtc::MutexLock lock(&state_->mutex); + state_->status = State::Status::kDead; +} + +void RunResolution(void* obj) { + std::function<void()>* function_ptr = + static_cast<std::function<void()>*>(obj); + (*function_ptr)(); + delete function_ptr; } void AsyncResolver::Start(const SocketAddress& addr) { RTC_DCHECK_RUN_ON(&sequence_checker_); RTC_DCHECK(!destroy_called_); addr_ = addr; - webrtc::TaskQueueBase* current_task_queue = webrtc::TaskQueueBase::Current(); - popup_thread_ = Thread::Create(); - popup_thread_->Start(); - popup_thread_->PostTask(webrtc::ToQueuedTask( - [this, flag = safety_.flag(), addr, current_task_queue] { + PlatformThread::SpawnDetached( + [this, addr, caller_task_queue = webrtc::TaskQueueBase::Current(), + state = state_] { std::vector<IPAddress> addresses; int error = ResolveHostname(addr.hostname().c_str(), addr.family(), &addresses); - current_task_queue->PostTask(webrtc::ToQueuedTask( - std::move(flag), [this, error, addresses = std::move(addresses)] { - RTC_DCHECK_RUN_ON(&sequence_checker_); - ResolveDone(std::move(addresses), error); - })); - })); + webrtc::MutexLock lock(&state->mutex); + if (state->status == State::Status::kLive) { + caller_task_queue->PostTask(webrtc::ToQueuedTask( + [this, error, addresses = std::move(addresses), state] { + bool live; + { + // ResolveDone can lead to instance destruction, so make sure + // we don't deadlock. + webrtc::MutexLock lock(&state->mutex); + live = state->status == State::Status::kLive; + } + if (live) { + RTC_DCHECK_RUN_ON(&sequence_checker_); + ResolveDone(std::move(addresses), error); + } + })); + } + }, + "AsyncResolver"); } bool AsyncResolver::GetResolvedAddress(int family, SocketAddress* addr) const { |