aboutsummaryrefslogtreecommitdiff
path: root/rtc_base/async_resolver.cc
diff options
context:
space:
mode:
Diffstat (limited to 'rtc_base/async_resolver.cc')
-rw-r--r--rtc_base/async_resolver.cc61
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 {