From bba8f1db307459988385faa4e79fd4aace397e36 Mon Sep 17 00:00:00 2001 From: Marcelo Fernandez Date: Sat, 6 May 2017 12:07:35 -0300 Subject: Fixed the IP resolver code blocking the main thread, it uses a Mutex now to lock its own thread. --- core/io/ip.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 18 deletions(-) (limited to 'core/io') diff --git a/core/io/ip.cpp b/core/io/ip.cpp index bf139eeacb..6c463b983c 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -68,6 +68,7 @@ struct _IP_ResolverPrivate { return IP::RESOLVER_INVALID_ID; } + Mutex *mutex; Semaphore *sem; Thread *thread; @@ -96,8 +97,10 @@ struct _IP_ResolverPrivate { while (!ipr->thread_abort) { ipr->sem->wait(); - GLOBAL_LOCK_FUNCTION; + + ipr->mutex->lock(); ipr->resolve_queues(); + ipr->mutex->unlock(); } } @@ -110,24 +113,30 @@ struct _IP_ResolverPrivate { IP_Address IP::resolve_hostname(const String &p_hostname, IP::Type p_type) { - GLOBAL_LOCK_FUNCTION; + resolver->mutex->lock(); String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type); - if (resolver->cache.has(key)) - return resolver->cache[key]; + if (resolver->cache.has(key)) { + IP_Address res = resolver->cache[key]; + resolver->mutex->unlock(); + return res; + } IP_Address res = _resolve_hostname(p_hostname, p_type); resolver->cache[key] = res; + resolver->mutex->unlock(); return res; } + IP::ResolverID IP::resolve_hostname_queue_item(const String &p_hostname, IP::Type p_type) { - GLOBAL_LOCK_FUNCTION; + resolver->mutex->lock(); ResolverID id = resolver->find_empty_id(); if (id == RESOLVER_INVALID_ID) { WARN_PRINT("Out of resolver queries"); + resolver->mutex->unlock(); return id; } @@ -146,6 +155,7 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String &p_hostname, IP::Typ resolver->resolve_queues(); } + resolver->mutex->unlock(); return id; } @@ -153,35 +163,51 @@ IP::ResolverStatus IP::get_resolve_item_status(ResolverID p_id) const { ERR_FAIL_INDEX_V(p_id, IP::RESOLVER_MAX_QUERIES, IP::RESOLVER_STATUS_NONE); - GLOBAL_LOCK_FUNCTION; - ERR_FAIL_COND_V(resolver->queue[p_id].status == IP::RESOLVER_STATUS_NONE, IP::RESOLVER_STATUS_NONE); + resolver->mutex->lock(); + if (resolver->queue[p_id].status == IP::RESOLVER_STATUS_NONE) { + ERR_PRINT("Condition status == IP::RESOLVER_STATUS_NONE"); + resolver->mutex->unlock(); + return IP::RESOLVER_STATUS_NONE; + } + IP::ResolverStatus res = resolver->queue[p_id].status; - return resolver->queue[p_id].status; + resolver->mutex->unlock(); + return res; } + IP_Address IP::get_resolve_item_address(ResolverID p_id) const { ERR_FAIL_INDEX_V(p_id, IP::RESOLVER_MAX_QUERIES, IP_Address()); - GLOBAL_LOCK_FUNCTION; + resolver->mutex->lock(); if (resolver->queue[p_id].status != IP::RESOLVER_STATUS_DONE) { - ERR_EXPLAIN("Resolve of '" + resolver->queue[p_id].hostname + "'' didn't complete yet."); - ERR_FAIL_COND_V(resolver->queue[p_id].status != IP::RESOLVER_STATUS_DONE, IP_Address()); + ERR_PRINTS("Resolve of '" + resolver->queue[p_id].hostname + "'' didn't complete yet."); + resolver->mutex->unlock(); + return IP_Address(); } - return resolver->queue[p_id].response; + IP_Address res = resolver->queue[p_id].response; + + resolver->mutex->unlock(); + return res; } + void IP::erase_resolve_item(ResolverID p_id) { ERR_FAIL_INDEX(p_id, IP::RESOLVER_MAX_QUERIES); - GLOBAL_LOCK_FUNCTION; + resolver->mutex->lock(); resolver->queue[p_id].status = IP::RESOLVER_STATUS_NONE; + + resolver->mutex->unlock(); } void IP::clear_cache(const String &p_hostname) { + resolver->mutex->lock(); + if (p_hostname.empty()) { resolver->cache.clear(); } else { @@ -190,7 +216,9 @@ void IP::clear_cache(const String &p_hostname) { resolver->cache.erase(_IP_ResolverPrivate::get_cache_key(p_hostname, IP::TYPE_IPV6)); resolver->cache.erase(_IP_ResolverPrivate::get_cache_key(p_hostname, IP::TYPE_ANY)); } -}; + + resolver->mutex->unlock(); +} Array IP::_get_local_addresses() const { @@ -249,12 +277,11 @@ IP::IP() { singleton = this; resolver = memnew(_IP_ResolverPrivate); resolver->sem = NULL; + resolver->mutex = Mutex::create(); #ifndef NO_THREADS - //resolver->sem = Semaphore::create(); - - resolver->sem = NULL; + resolver->sem = Semaphore::create(); if (resolver->sem) { resolver->thread_abort = false; @@ -281,7 +308,9 @@ IP::~IP() { memdelete(resolver->thread); memdelete(resolver->sem); } - memdelete(resolver); #endif + + memdelete(resolver->mutex); + memdelete(resolver); } -- cgit v1.2.3