在Python中调用exit()时,C ++析构函数中的互斥锁会导致异常
我有一个应用程序加载了一个处理队列中作业的类。 为了保持线程安全,只要队列被修改,就会锁定互斥锁。 当应用程序退出并且调用析构函数时,互斥锁被锁定以清除队列。
然而,当我在Python中加载这个DLL时,创建一个对象的实例,并调用exit()
(在Python中),当互斥锁试图锁定时会引发异常:
Microsoft Visual Studio C运行时库已在python.exe中检测到致命错误。
我已经简化了析构函数,直到在本地创建一个互斥锁并尝试锁定它,并且仍然可以重现该问题:
QueueHandler::~QueueHandler(void)
{
mutex mut; // in reality, this is a member of the class and there are actual operations between lock and unlock
mut.lock(); // exception here
mut.unlock();
}
如果我使用未修改的代码,只需在队列操作周围删除锁定,它就可以正常工作。
这是调用堆栈看似相关的部分:
KernelBase.dll!RaiseException() Unknown
msvcr120.dll!_CxxThrowException(void * pExceptionObject, const _s__ThrowInfo * pThrowInfo) Line 154 C++
msvcr120.dll!Concurrency::details::SchedulerBase::SchedulerBase(const Concurrency::SchedulerPolicy & policy) Line 149 C++
msvcr120.dll!Concurrency::details:: SchedulerBase::CreateWithoutInitializing(const Concurrency::SchedulerPolicy & policy) Line 285 C++
msvcr120.dll!Concurrency::details:: SchedulerBase::CreateContextFromDefaultScheduler() Line 571 C++
msvcr120.dll!Concurrency::details::SchedulerBase::CurrentContext() Line 404 C++
[Inline Frame] msvcr120.dll!Concurrency::details::LockQueueNode::{ctor (unsigned int) Line 619 C++
msvcr120.dll!Concurrency::critical_section::lock() Line 1031 C++
msvcp120.dll!mtx_do_lock(_Mtx_internal_imp_t * * mtx, const xtime * target) Line 67 C++
--> MyApplication.dll!QueueHandler::~QueueHandler() Line 106 C++
MyApplication.dll!_CRT_INIT(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 416 C
MyApplication.dll!__DllMainCRTStartup(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 522 C
ntdll.dll!LdrShutdownProcess() Unknown
ntdll.dll!RtlExitUserProcess() Unknown
msvcr100.dll!doexit(int code, int quick, int retcaller) Line 621 C
python27.dll!000000001e13be65() Unknown
...
python27.dll!000000001e043494() Unknown
python.exe!000000001d00119e() Unknown
问题:
exit()
时会有所不同? 编辑: MCVE: QueueHandlerApp - 运行该应用程序或运行script.py来演示该问题。
有些人遇到问题时会想:“我知道,我会用懒惰的初始化。” 现在他们有两个问题。
这是std::mutex
MSVC实现中的一个错误。 在MSVC14 std::mutex
和std::condition_variable
会懒惰地执行一些内部初始化。 这一点很糟糕,但由于Windows上的模块未初始化而变得更糟。
该错误在MSVC14(Visual Studio 2015)中修复 - std::mutex
被重写为SRWLock
内部使用SRWLock
。 SRWLock
是一个简单的原语,没有额外的依赖关系。 它仅依赖于原子指令和键控事件系统调用。 由于内核与用户空间隔离, SRWLock
无论在什么地方使用都应该可以SRWLock
地工作。
看起来像你正在使用MSVC12(Visual Studio 2013)。 您应该切换到MSVC14(Visual Studio 2015)或使用Boost.Thread。
实际上MSVC12和更早版本的std::mutex
存在很多问题。 有些与CRT中使用的实际实现有关,其他(如我所知)是由Windows 7中的错误引起的,并在Windows 8中得到修复。
上一篇: Mutex lock in C++ destructor causes exception when exit() called in Python