我有一个应用程序,它使用一个处理队列中作业的类来加载DLL。为了保证线程安全,每当修改队列时都会锁定互斥锁。当应用程序退出并调用析构函数时,会锁定互斥锁以清除队列。
但是,当我在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来演示此问题。
答案 0 :(得分:0)
有些人在遇到问题时会想,"我知道,我会用 懒惰的初始化。"现在他们有两个问题。
这是std::mutex
的MSVC实施中的错误。在MSVC14 std::mutex
和std::condition_variable
之前,懒惰地执行一些内部初始化。仅这一点坏,但由于how modules are deinitialized on Windows而变得更糟。
该错误已在MSVC14中修复(Visual Studio 2015) - std::mutex
被重写为在内部使用SRWLock
。 SRWLock
是一个简单的原语,没有其他依赖项。它仅依赖于原子指令和Keyed Events系统调用。由于内核与用户空间隔离,SRWLock
无论在何处使用都应该无法正常工作。
好像您正在使用MSVC12(Visual Studio 2013)。您应该切换到MSVC14(Visual Studio 2015)或使用Boost.Thread。
MSVC12及更早版本的std::mutex
实际上存在很多问题。有些与CRT中使用的实际实现有关,其他(如我所见)是由Windows 7中的错误引起的,并且已在Windows 8中修复。