4

std::mutex以下からミューテックスがロックされるとデッドロックがDllMain()発生します。これは、問題を示す最小限のDLLテストケースです。私の実際のコードは、通常の機能中に初期化の外部でも使用できるメンバー関数を使用しているため、ミューテックスロックを実行します。

main()問題は、スレッドの呼び出しスタックに見られるスケジューラーと、スケジューラーによって生成された(おそらく)他のスレッドとの間のデッドロックだと思います。デッドロックmain()は、実際に実行される前に発生しているようです。

デッドロックを修正/解決する方法についてアドバイスをいただければ幸いです。

単純な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;
}

デッドロックの時点で、プロセスには2つのスレッドがあります。

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

2番目のスレッドの呼び出しスタックは短いです:

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

編集1:

WinDbgは、それがローダーロックの問題であることを確認します。

PRIMARY_PROBLEM_CLASS:  APPLICATION_HANG_HungIn_LoaderLock
4

2 に答える 2

5

DLLを作成するためのベストプラクティスドキュメントを確認してください。

DllMain内から次のタスクを実行しないでください。

  • LoadLibraryまたはLoadLibraryExを(直接または間接的に)呼び出します。これにより、デッドロックまたはクラッシュが発生する可能性があります。
  • 他のスレッドと同期します。これにより、デッドロックが発生する可能性があります。
于 2013-02-14T10:32:05.070 に答える
1

キューの初期化の使用QueueUserAPC()は、常に main() の前に実行されますが、恐ろしいローダー ロックの外で実行されるようです。これは私の問題の解決策のようです。

編集1

いくつかのテストの後、APC をキューに入れると APC メソッドが機能するように見えDllMain()ますが、クラスの静的グローバル インスタンスの ctor から APC をキューに入れると機能しません。IOW、APC の使用は、コンパイラとビルド モードのすべての可能な組み合わせで均一に使用できるわけではありません。

于 2013-02-06T10:39:57.577 に答える