I came across a strange Boost (v1.38) mutex deadlock in a preexisting .NET (C#, 3.5) application that makes calls to a C++ library. An exception is [properly] thrown at a point after a read lock is obtained and that exception goes unhandled all the way back to the managed .NET code (where it is handled). The next call to the c++ library that attempts to use a setter method hangs on the unique lock aquisition indefinately (presumably the read lock was not released):
ntdll.dll!NtWaitForSingleObject() + 0x15 bytes
kernel32.dll!WaitForSingleObjectEx() + 0x43 bytes
kernel32.dll!WaitForSingleObject() + 0x12 bytes
OurCPPLib.dll!boost::shared_mutex::unlock_upgrade_and_lock() Line 478 + 0x11 bytes C++
OurCPPLib.dll!boost::unique_lock<boost::shared_mutex>::unique_lock<boost::shared_mutex>(boost::detail::thread_move_t<boost::upgrade_lock<boost::shared_mutex> > other) Line 788 C++
OurCPPLib.dll!boost::upgrade_to_unique_lock<boost::shared_mutex>::upgrade_to_unique_lock<boost::shared_mutex>(boost::upgrade_lock<boost::shared_mutex> & m_) Line 802 + 0x98 bytes C++
OurCPPLib.dll!OurClass::SetSomething(double something) Line 95 C++
The class defines a number of Get and Set methods (readers/writers) and implements them like so:
boost::shared_mutex _calcSharedMutex;
RETURNCODE GetSomething(double& something)
{
boost::shared_lock<boost::shared_mutex> lock(_calcSharedMutex);
return _anotherObject->GetSomething(something);
}
RETURNCODE SetSomething(double something)
{
boost::upgrade_lock<boost::shared_mutex> lock(_calcSharedMutex);
boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock);
return _anotherObject->SetSomething(something);
}
The call to _anotherObject->GetSomething() will throw an exception in a rare condition:
throw std::invalid_argument("Unknown something");
Also, there are some calls within getters to _anotherObject->GetSomething() that are made within a try/catch in the C++ library itself, preventing the exception from going back to the managed code, and that does not cause this deadlock. Does the unhandled exception break the boost mutex scope unlocking?
Thanks in advance to anyone that may have some insight!