exception抛出后,Boost共享互斥锁未释放

我在预先存在的.NET(C#,3.5)应用程序中遇到了一个奇怪的Boost(v1.38)互斥锁死锁,该应用程序调用C ++库。 在获得读取锁定之后的某个时刻[正确]抛出一个exception,并且该exception一直未处理回托管.NET代码(处理它的位置)。 尝试使用setter方法的c ++库的下一次调用会无限期地挂起唯一的锁定获取(可能是未释放读取锁定):

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::unique_lock(boost::detail::thread_move_t<boost::upgrade_lock > other) Line 788 C++ OurCPPLib.dll!boost::upgrade_to_unique_lock::upgrade_to_unique_lock(boost::upgrade_lock & m_) Line 802 + 0x98 bytes C++ OurCPPLib.dll!OurClass::SetSomething(double something) Line 95 C++ 

该类定义了许多Get和Set方法(读者/编写者)并像这样实现它们:

 boost::shared_mutex _calcSharedMutex; RETURNCODE GetSomething(double& something) { boost::shared_lock lock(_calcSharedMutex); return _anotherObject->GetSomething(something); } RETURNCODE SetSomething(double something) { boost::upgrade_lock lock(_calcSharedMutex); boost::upgrade_to_unique_lock uniqueLock(lock); return _anotherObject->SetSomething(something); } 

对_anotherObject-> GetSomething()的调用将在极少数情况下抛出exception:

 throw std::invalid_argument("Unknown something"); 

此外,在getter中有一些调用_anotherObject-> GetSomething(),这些调用是在C ++库本身的try / catch中进行的,防止exception返回到托管代码,并且不会导致此死锁。 未处理的exception是否会破坏boost mutex范围的解锁?

提前感谢任何可能有一些见解的人!

在C ++中未指定在抛出未处理的exception时是否展开堆栈。 一些实现这样做(调用析构函数和其他应该发生的事情),而其他实现则不然。 我不确切知道C ++ / CLI如何处理这个问题,但是如果C ++部分将exception视为未处理,那么它可能不会展开堆栈,因此不会调用析构函数并释放互斥锁。

(如果是这样,只需在C ++代码中捕获并重新抛出exception即可解决问题)

但这只是猜测。 我从未使用过很多C ++ / CLI,我也不知道如何在本机代码和托管代码之间传播exception。

2.0 CLR中存在一个错误,当托管代码中处理本机生成的exception时,该错误会阻止堆栈展开。

Microsoft Connect:/ Ehsc&/ Eha&stack unwinding

切换托管可执行文件以在4.0 CLR上运行更正了问题。

作为旁注,本机C ++库是从一个针对2.0 CLR的托管C#库调用的。 托管程序集可以继续以2.0 CLR为目标,因为它将在可执行文件(4.0)的无错误CLR上执行,但它将以2.0兼容模式执行。