gpt4 book ai didi

python - 在 Python 中调用 exit() 时,C++ 析构函数中的互斥锁会导致异常

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:09:09 25 4
gpt4 key购买 nike

我有一个应用程序加载了一个 DLL,其中包含一个处理队列中作业的类。为了保持线程安全,只要队列被修改,互斥锁就会被锁定。当应用程序退出并调用析构函数时,互斥锁被锁定以清除队列。

但是,当我在 Python 中加载此 DLL、创建对象的实例并调用 exit()(在 Python 中)时,当互斥体试图锁定时会抛出异常:

Microsoft Visual Studio C Runtime Library has detected a fatal error in 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

问题:

  1. 如果这段代码在我正常退出我的应用程序(关闭 GUI)时有效,为什么当我从 Pyton exit() 时它会有所不同?
  2. 是否有“更正确”的退出 Python 的方法?
  3. 这可能与所使用的互斥锁/锁的类型有关吗?
  4. 我什至需要在我的析构函数中用队列操作锁定该部分吗?或者不用锁就可以删除队列中的对象?

编辑:MCVE: QueueHandlerApp - 运行应用程序或运行 script.py 来演示问题。

最佳答案

Some people, when confronted with a problem, think, "I know, I'll use lazy initialization." Now they have two problems.

这是 std::mutex 的 MSVC 实现中的错误。在 MSVC14 之前,std::mutexstd::condition_variable 会懒惰地执行一些内部初始化。这本身就不好,但由于 how modules are deinitialized on Windows 而变得更糟.

该错误已在 MSVC14 (Visual Studio 2015) 中修复 - std::mutex 被重写为在内部使用 SRWLockSRWLock 是一个没有附加依赖项的简单原语。它仅依赖于原子指令和 Keyed Events系统调用。由于内核与用户空间隔离,SRWLock 无论在何处使用,都应该无缝运行。

您似乎正在使用 MSVC12 (Visual Studio 2013)。您应该切换到 MSVC14 (Visual Studio 2015) 或改用 Boost.Thread。

在 MSVC12 及更早版本上,std::mutex 实际上存在很多问题。有些与 CRT 中使用的实际实现有关,其他(据我所知)是由 Windows 7 中的错误引起的,并已在 Windows 8 中修复。

关于python - 在 Python 中调用 exit() 时,C++ 析构函数中的互斥锁会导致异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44555289/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com