diff --git a/src/inet/AsyncDNSResolverSockets.cpp b/src/inet/AsyncDNSResolverSockets.cpp index dabe0dba34..cdde16627f 100644 --- a/src/inet/AsyncDNSResolverSockets.cpp +++ b/src/inet/AsyncDNSResolverSockets.cpp @@ -37,6 +37,29 @@ namespace nl { namespace Inet { +class LockHolder { + public: + LockHolder(AsyncDNSResolverSockets& resolver) + :mResolver(resolver) + { + int pthreadErr; + + pthreadErr = pthread_mutex_lock(&mResolver.mAsyncDNSMutex); + VerifyOrDie(pthreadErr == 0); + } + + ~LockHolder() + { + int pthreadErr; + + pthreadErr = pthread_mutex_unlock(&mResolver.mAsyncDNSMutex); + VerifyOrDie(pthreadErr == 0); + } + + private: + AsyncDNSResolverSockets& mResolver; +}; + /** * The explicit initializer for the AsynchronousDNSResolverSockets class. * This initializes the mutex and semaphore variables and creates the @@ -87,14 +110,14 @@ INET_ERROR AsyncDNSResolverSockets::Shutdown(void) INET_ERROR err = INET_NO_ERROR; int pthreadErr; - AsyncMutexLock(); - - mInet->State = InetLayer::kState_ShutdownInProgress; + { + LockHolder asyncMutexLock(*this); - pthreadErr = pthread_cond_broadcast(&mAsyncDNSCondVar); - VerifyOrDie(pthreadErr == 0); + mInet->State = InetLayer::kState_ShutdownInProgress; - AsyncMutexUnlock(); + pthreadErr = pthread_cond_broadcast(&mAsyncDNSCondVar); + VerifyOrDie(pthreadErr == 0); + } // Have the Weave thread join the thread pool for asynchronous DNS resolution. for (int i = 0; i < INET_CONFIG_DNS_ASYNC_MAX_THREAD_COUNT; i++) @@ -172,8 +195,7 @@ INET_ERROR AsyncDNSResolverSockets::EnqueueRequest(DNSResolver &resolver) { INET_ERROR err = INET_NO_ERROR; int pthreadErr; - - AsyncMutexLock(); + LockHolder asyncMutexLock(*this); // Add the DNSResolver object to the queue. if (mAsyncDNSQueueHead == NULL) @@ -191,8 +213,6 @@ INET_ERROR AsyncDNSResolverSockets::EnqueueRequest(DNSResolver &resolver) pthreadErr = pthread_cond_signal(&mAsyncDNSCondVar); VerifyOrDie(pthreadErr == 0); - AsyncMutexUnlock(); - return err; } @@ -205,8 +225,7 @@ INET_ERROR AsyncDNSResolverSockets::DequeueRequest(DNSResolver **outResolver) { INET_ERROR err = INET_NO_ERROR; int pthreadErr; - - AsyncMutexLock(); + LockHolder asyncMutexLock(*this); // block until there is work to do or we detect a shutdown while ( (mAsyncDNSQueueHead == NULL) && @@ -236,8 +255,6 @@ INET_ERROR AsyncDNSResolverSockets::DequeueRequest(DNSResolver **outResolver) } } - AsyncMutexUnlock(); - return err; } @@ -249,13 +266,10 @@ INET_ERROR AsyncDNSResolverSockets::DequeueRequest(DNSResolver **outResolver) INET_ERROR AsyncDNSResolverSockets::Cancel(DNSResolver &resolver) { INET_ERROR err = INET_NO_ERROR; - - AsyncMutexLock(); + LockHolder asyncMutexLock(*this); resolver.mState = DNSResolver::kState_Canceled; - AsyncMutexUnlock(); - return err; } @@ -282,7 +296,7 @@ void AsyncDNSResolverSockets::Resolve(DNSResolver &resolver) gaiReturnCode = getaddrinfo(resolver.asyncHostNameBuf, NULL, &gaiHints, &gaiResults); // Mutex protects the read and write operation on resolver->mState - AsyncMutexLock(); + LockHolder asyncMutexLock(*this); // Process the return code and results list returned by getaddrinfo(). If the call // was successful this will copy the resultant addresses into the caller's array. @@ -291,9 +305,6 @@ void AsyncDNSResolverSockets::Resolve(DNSResolver &resolver) // Set the DNS resolver state. resolver.mState = DNSResolver::kState_Complete; - // Release lock. - AsyncMutexUnlock(); - return; } @@ -348,22 +359,6 @@ void *AsyncDNSResolverSockets::AsyncDNSThreadRun(void *args) return NULL; } -void AsyncDNSResolverSockets::AsyncMutexLock(void) -{ - int pthreadErr; - - pthreadErr = pthread_mutex_lock(&mAsyncDNSMutex); - VerifyOrDie(pthreadErr == 0); -} - -void AsyncDNSResolverSockets::AsyncMutexUnlock(void) -{ - int pthreadErr; - - pthreadErr = pthread_mutex_unlock(&mAsyncDNSMutex); - VerifyOrDie(pthreadErr == 0); -} - } // namespace Inet } // namespace nl #endif // INET_CONFIG_ENABLE_DNS_RESOLVER && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS diff --git a/src/inet/AsyncDNSResolverSockets.h b/src/inet/AsyncDNSResolverSockets.h index 9e0550d103..cab217d096 100644 --- a/src/inet/AsyncDNSResolverSockets.h +++ b/src/inet/AsyncDNSResolverSockets.h @@ -54,6 +54,7 @@ class AsyncDNSResolverSockets { friend class InetLayer; friend class DNSResolver; + friend class LockHolder; public: INET_ERROR EnqueueRequest(DNSResolver &resolver); @@ -88,10 +89,6 @@ class AsyncDNSResolverSockets static void *AsyncDNSThreadRun(void *args); static void NotifyWeaveThread(DNSResolver *resolver); - - void AsyncMutexLock(void); - - void AsyncMutexUnlock(void); }; } // namespace Inet diff --git a/src/inet/DNSResolver.cpp b/src/inet/DNSResolver.cpp index 126941ebc7..9612026a96 100644 --- a/src/inet/DNSResolver.cpp +++ b/src/inet/DNSResolver.cpp @@ -91,9 +91,9 @@ INET_ERROR DNSResolver::Resolve(const char *hostName, uint16_t hostNameLen, uint DNSResolver::OnResolveCompleteFunct onComplete, void *appState) { INET_ERROR res = INET_NO_ERROR; + Weave::System::Object::AutoRelease objectRelease(*this); #if !WEAVE_SYSTEM_CONFIG_USE_SOCKETS && !LWIP_DNS - Release(); return INET_ERROR_NOT_IMPLEMENTED; #endif // !WEAVE_SYSTEM_CONFIG_USE_SOCKETS && !LWIP_DNS @@ -108,7 +108,6 @@ INET_ERROR DNSResolver::Resolve(const char *hostName, uint16_t hostNameLen, uint addrFamilyOption != kDNSOption_AddrFamily_IPv6Preferred) || (optionFlags & ~kDNSOption_ValidFlags) != 0) { - Release(); return INET_ERROR_BAD_ARGS; } @@ -164,7 +163,6 @@ INET_ERROR DNSResolver::Resolve(const char *hostName, uint16_t hostNameLen, uint if (addrFamilyOption == kDNSOption_AddrFamily_IPv6Only) #endif { - Release(); return INET_ERROR_NOT_IMPLEMENTED; } @@ -202,7 +200,6 @@ INET_ERROR DNSResolver::Resolve(const char *hostName, uint16_t hostNameLen, uint else if (lwipErr != ERR_INPROGRESS) { res = Weave::System::MapErrorLwIP(lwipErr); - Release(); } return res; @@ -228,9 +225,6 @@ INET_ERROR DNSResolver::Resolve(const char *hostName, uint16_t hostNameLen, uint // Invoke the caller's completion function. onComplete(appState, res, NumAddrs, addrArray); - // Release DNSResolver object. - Release(); - return INET_NO_ERROR; #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS @@ -298,12 +292,11 @@ INET_ERROR DNSResolver::Cancel() */ void DNSResolver::HandleResolveComplete() { + Weave::System::Object::AutoRelease objectRelease(*this); + // Call the application's completion handler if the request hasn't been canceled. if (OnComplete != NULL) OnComplete(AppState, (NumAddrs > 0) ? INET_NO_ERROR : INET_ERROR_HOST_NOT_FOUND, NumAddrs, AddrArray); - - // Release the resolver object. - Release(); } @@ -530,13 +523,13 @@ uint8_t DNSResolver::CountAddresses(int family, const struct addrinfo * addrs) void DNSResolver::HandleAsyncResolveComplete(void) { + Weave::System::Object::AutoRelease objectRelease(*this); + // Copy the resolved address to the application supplied buffer, but only if the request hasn't been canceled. if (OnComplete && mState != kState_Canceled) { OnComplete(AppState, asyncDNSResolveResult, NumAddrs, AddrArray); } - - Release(); } #endif // INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS diff --git a/src/system/SystemObject.h b/src/system/SystemObject.h index 00e0377391..8295705b41 100644 --- a/src/system/SystemObject.h +++ b/src/system/SystemObject.h @@ -82,6 +82,21 @@ class NL_DLL_EXPORT Object void Release(void); Layer& SystemLayer(void) const; + class AutoRelease { + public: + AutoRelease(Object& owner) : mOwner(owner) + { + } + + ~AutoRelease(void) + { + mOwner.Release(); + } + + private: + Object& mOwner; + }; + protected: #if WEAVE_SYSTEM_CONFIG_USE_LWIP /**< What to do when DeferredRelease fails to post a kEvent_ReleaseObj. */