-
Notifications
You must be signed in to change notification settings - Fork 105
New to openweave #492
base: master
Are you sure you want to change the base?
New to openweave #492
Changes from all commits
de6ef5c
00ef599
25827d5
aa70426
9ed08b2
000a781
a3e7c4e
fce2625
397a55a
2b1c818
9d999fd
d7fc131
749856a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to above, I think this pattern makes it easy to miss the acquisition of the lock. I suggest always using an independent block to clearly demark the scope of the lock, with the lock being the only variable declared at the start of the block. E.g.:
|
||
|
||
// 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 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to my comment below, I don't see this as a desirable pattern. Rather, I would argue that the returns should be replaced with ExitNow() jumps to an exit: label containing a single call to Release(). |
||
|
||
#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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see this as an anti-pattern. In this case we're dealing with a reference count, vs. a lock, where the lifetime of reference spans multiple states of the object. In this case, a single call to a method called Release() is clearly the most obvious pattern. |
||
|
||
// 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 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This illustrates one of the downsides of this pattern--the point at which the lock is acquired doesn't read as an imperative statement, and hence is easily missed by the unaware reader.
I think a construct like this would be more obvious: