<i id='ct0Ci'><tr id='ct0Ci'><dt id='ct0Ci'><q id='ct0Ci'><span id='ct0Ci'><b id='ct0Ci'><form id='ct0Ci'><ins id='ct0Ci'></ins><ul id='ct0Ci'></ul><sub id='ct0Ci'></sub></form><legend id='ct0Ci'></legend><bdo id='ct0Ci'><pre id='ct0Ci'><center id='ct0Ci'></center></pre></bdo></b><th id='ct0Ci'></th></span></q></dt></tr></i><div id='ct0Ci'><tfoot id='ct0Ci'></tfoot><dl id='ct0Ci'><fieldset id='ct0Ci'></fieldset></dl></div>
    <tfoot id='ct0Ci'></tfoot>

    <small id='ct0Ci'></small><noframes id='ct0Ci'>

      <bdo id='ct0Ci'></bdo><ul id='ct0Ci'></ul>
  1. <legend id='ct0Ci'><style id='ct0Ci'><dir id='ct0Ci'><q id='ct0Ci'></q></dir></style></legend>

      当从 DllMain() 锁定时,Visual Studio 2012 中的 C++11 std::mutex 会死锁

      C++11 std::mutex in Visual Studio 2012 deadlock when locked from DllMain()(当从 DllMain() 锁定时,Visual Studio 2012 中的 C++11 std::mutex 会死锁)

        <bdo id='rtju9'></bdo><ul id='rtju9'></ul>
            <tbody id='rtju9'></tbody>
          • <tfoot id='rtju9'></tfoot>

              <legend id='rtju9'><style id='rtju9'><dir id='rtju9'><q id='rtju9'></q></dir></style></legend>
            • <small id='rtju9'></small><noframes id='rtju9'>

              <i id='rtju9'><tr id='rtju9'><dt id='rtju9'><q id='rtju9'><span id='rtju9'><b id='rtju9'><form id='rtju9'><ins id='rtju9'></ins><ul id='rtju9'></ul><sub id='rtju9'></sub></form><legend id='rtju9'></legend><bdo id='rtju9'><pre id='rtju9'><center id='rtju9'></center></pre></bdo></b><th id='rtju9'></th></span></q></dt></tr></i><div id='rtju9'><tfoot id='rtju9'></tfoot><dl id='rtju9'><fieldset id='rtju9'></fieldset></dl></div>

                本文介绍了当从 DllMain() 锁定时,Visual Studio 2012 中的 C++11 std::mutex 会死锁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                问题描述

                当互斥锁从 DllMain() 锁定时,我看到 std::mutex 出现死锁 下面是一个最小的 DLL 测试用例,它向我展示了这个问题.我的实际代码执行互斥锁,因为它使用的成员函数在正常函数期间也可在初始化之外使用.

                I am seeing a deadlock with std::mutex when the mutex is locked from DllMain() Below is a minimal DLL test case that exhibits the problem for me. My actual code does the mutex locking because it uses member functions that are also usable outside initialization during normal function.

                我认为问题是调度程序之间的死锁,如 main() 线程的调用堆栈和调度程序产生的另一个线程(可能)所见.死锁似乎发生在 main() 实际执行之前.

                I think that the problem is a deadlock between the scheduler as seen in the call stack of main() thread and the other thread (probably) spawned by the scheduler. The deadlock seems to happen before main() is actually executed.

                对于如何修复/解决死锁的任何建议,我将不胜感激.

                I would appreciate any advice as to how to fix/resolve the deadlock.

                简单的 DLL:

                static void testFunc()
                {
                    std::mutex mtx;
                    mtx.lock();
                
                    mtx.unlock();
                }
                
                
                BOOL APIENTRY DllMain( HMODULE hModule,
                                       DWORD  ul_reason_for_call,
                                       LPVOID lpReserved
                                     )
                {
                    switch (ul_reason_for_call)
                    {
                    case DLL_PROCESS_ATTACH:
                        testFunc ();
                        break;
                
                    case DLL_THREAD_ATTACH:
                        testFunc ();
                        break;
                
                    case DLL_THREAD_DETACH:
                    case DLL_PROCESS_DETACH:
                        break;
                    }
                    return TRUE;
                }
                

                在死锁点,进程中有两个线程:

                At the point of the deadlock there are two threads in the process:

                Not Flagged >   6408    0   Main Thread Main Thread msvcr110d.dll!Concurrency::details::SchedulerBase::SchedulerBase    Normal
                Not Flagged     7600    0   Worker Thread   ntdll.dll!_TppWaiterpThread@4() ntdll.dll!_NtDelayExecution@8   Normal
                

                这里是main()线程的调用栈:

                    ntdll.dll!_NtWaitForKeyedEvent@16() Unknown
                    ntdll.dll!_TppWaitpSet@16() Unknown
                    ntdll.dll!_TppSetWaitInterrupt@12() Unknown
                    ntdll.dll!_RtlRegisterWait@24() Unknown
                    kernel32.dll!_RegisterWaitForSingleObject@24()  Unknown
                >   msvcr110d.dll!Concurrency::details::SchedulerBase::SchedulerBase(const Concurrency::SchedulerPolicy & policy) Line 152  C++
                    msvcr110d.dll!Concurrency::details::ThreadScheduler::ThreadScheduler(const Concurrency::SchedulerPolicy & policy) Line 26   C++
                    msvcr110d.dll!Concurrency::details::ThreadScheduler::Create(const Concurrency::SchedulerPolicy & policy) Line 34    C++
                    msvcr110d.dll!Concurrency::details::SchedulerBase::CreateWithoutInitializing(const Concurrency::SchedulerPolicy & policy) Line 276  C++
                    msvcr110d.dll!Concurrency::details::SchedulerBase::GetDefaultScheduler() Line 650   C++
                    msvcr110d.dll!Concurrency::details::SchedulerBase::CreateContextFromDefaultScheduler() Line 567 C++
                    msvcr110d.dll!Concurrency::details::SchedulerBase::CurrentContext() Line 399    C++
                    msvcr110d.dll!Concurrency::details::LockQueueNode::LockQueueNode(unsigned int timeout) Line 616 C++
                    msvcr110d.dll!Concurrency::critical_section::lock() Line 1017   C++
                    msvcp110d.dll!mtx_do_lock(_Mtx_internal_imp_t * * mtx, const xtime * target) Line 65    C++
                    msvcp110d.dll!_Mtx_lock(_Mtx_internal_imp_t * * mtx) Line 144   C++
                    ConsoleApplicationDll.dll!std::_Mtx_lockX(_Mtx_internal_imp_t * * _Mtx) Line 68 C++
                    ConsoleApplicationDll.dll!std::_Mutex_base::lock() Line 43  C++
                    ConsoleApplicationDll.dll!testFunc() Line 16    C++
                    ConsoleApplicationDll.dll!DllMain(HINSTANCE__ * hModule, unsigned long ul_reason_for_call, void * lpReserved) Line 29   C++
                    ConsoleApplicationDll.dll!__DllMainCRTStartup(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 508    C
                    ConsoleApplicationDll.dll!_DllMainCRTStartup(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 472 C
                    ntdll.dll!_LdrpCallInitRoutine@16() Unknown
                    ntdll.dll!_LdrpRunInitializeRoutines@4()    Unknown
                    ntdll.dll!_LdrpInitializeProcess@8()    Unknown
                    ntdll.dll!__LdrpInitialize@8()  Unknown
                    ntdll.dll!_LdrInitializeThunk@8()   Unknown
                

                第二个线程的调用栈很短:

                The second thread's call stack is short:

                >   ntdll.dll!_NtDelayExecution@8() Unknown
                    ntdll.dll!__LdrpInitialize@8()  Unknown
                    ntdll.dll!_LdrInitializeThunk@8()   Unknown
                

                编辑 1:

                WinDbg 确认是加载程序锁定问题:

                WinDbg confirms that it is loader lock issue:

                PRIMARY_PROBLEM_CLASS:  APPLICATION_HANG_HungIn_LoaderLock
                

                推荐答案

                似乎使用 QueueUserAPC() 进行队列初始化总是在 main() 之前执行,但在可怕的加载器锁之外.这看起来像是我的问题的解决方案.

                It seems that using QueueUserAPC() to queue initialization is always executed before main() but out of the dreaded loader lock. This looks like a solution to my problem.

                编辑 1

                经过一些测试,如果我将来自 DllMain() 的 APC 排队,APC 方法似乎有效,但如果我将 APC 从一个类的静态全局实例的 ctor 排队,则它不起作用.IOW,对我来说,在编译器和构建模式的所有可能组合中使用 APC 并不是统一可用的.

                After some testing it seems that the APC method works if I queue the APC from DllMain() but it does not work if I queue the APC from a ctor of a static global instance of a class. IOW, using the APC is not uniformly usable across all possible combinations of compilers and build modes for me.

                这篇关于当从 DllMain() 锁定时,Visual Studio 2012 中的 C++11 std::mutex 会死锁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

                相关文档推荐

                What is inside .lib file of Static library, Statically linked dynamic library and dynamically linked dynamic library?(静态库、静态链接动态库和动态链接动态库的 .lib 文件里面是什么?)
                How do I load a C DLL from the SXS in Python?(如何从 Python 中的 SXS 加载 C DLL?)
                Can Cython code be compiled to a dll so C++ application can call it?(Cython 代码可以编译成 dll 以便 C++ 应用程序可以调用它吗?)
                Delay Loading DLLs(延迟加载 DLL)
                Throwing C++ exceptions across DLL boundaries(跨 DLL 边界抛出 C++ 异常)
                Loading a dll from a dll?(从 dll 加载 dll?)
                  <tbody id='H0n6A'></tbody>

                  <small id='H0n6A'></small><noframes id='H0n6A'>

                  <tfoot id='H0n6A'></tfoot>
                    <bdo id='H0n6A'></bdo><ul id='H0n6A'></ul>
                  • <i id='H0n6A'><tr id='H0n6A'><dt id='H0n6A'><q id='H0n6A'><span id='H0n6A'><b id='H0n6A'><form id='H0n6A'><ins id='H0n6A'></ins><ul id='H0n6A'></ul><sub id='H0n6A'></sub></form><legend id='H0n6A'></legend><bdo id='H0n6A'><pre id='H0n6A'><center id='H0n6A'></center></pre></bdo></b><th id='H0n6A'></th></span></q></dt></tr></i><div id='H0n6A'><tfoot id='H0n6A'></tfoot><dl id='H0n6A'><fieldset id='H0n6A'></fieldset></dl></div>

                      1. <legend id='H0n6A'><style id='H0n6A'><dir id='H0n6A'><q id='H0n6A'></q></dir></style></legend>