【发布时间】:2014-05-17 09:34:43
【问题描述】:
我在调用 C++ 库的现有 .NET (C#, 3.5) 应用程序中遇到了一个奇怪的 Boost (v1.38) 互斥锁死锁。在获得读取锁之后的某个时间点 [正确] 抛出异常,并且该异常一直未处理,一直返回到托管 .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<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++
该类定义了许多 Get 和 Set 方法(读取器/写入器)并像这样实现它们:
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);
}
调用 _anotherObject->GetSomething() 会在极少数情况下抛出异常:
throw std::invalid_argument("Unknown something");
此外,getter 中有一些调用 _anotherObject->GetSomething() 是在 C++ 库本身的 try/catch 中进行的,从而防止异常返回到托管代码,并且不会导致这种死锁.未处理的异常是否会破坏 boost mutex 范围的解锁?
提前感谢任何可能有一些见解的人!
【问题讨论】:
-
这段代码是用 /clr 编译的吗?如果是,您是否在其前面添加了#pragma managed(push, off)?
-
c++ 没有使用 /clr 开关编译。
-
这很奇怪,这应该可以。除了实际显示问题的演示程序之外,您唯一的其他选择是使用 /EHa 编译该 C++ 代码。尽管 that 会起作用是没有意义的。
标签: c# c++ boost mutex deadlock