6

遅延ロードされたDLL内に1つのインスタンス(グローバル/静的オブジェクト)ClassAがあります。内部のこのオブジェクトには、正常なシャットダウンを実行するために必要な「オブザーバー」スレッドがあります。FreeLibraryを呼び出すと、この静的オブジェクトの削除中に、スレッドがシャットダウンを要求しましたが、_endthreadex()でハングし、デッドロックが発生することに気付きました。_endthreadexを明示的に呼び出すか暗黙的に呼び出すかは関係ありません。オブジェクトがグローバルであるか静的であるかは関係ありません-同じ結果です。このスレッドはClassBでラップされています(カスタムメッセージループを使用してテンプレートによって実装されます)。スレッドをシャットダウンする要求(メッセージの投稿)があり、WaitForSingleObjectに続いて、指定されたスレッドハンドルに対して戻ることはありません。

コードとシャットダウンのどこでも使用されているのと同じ「テンプレートスレッドクラス」がうまく機能します。静的オブジェクトを削除するときの唯一の問題。_endthreadex()の内部には、dllのアンロードと静的オブジェクトの削除時にすでにロックされているロックがあると思います。

スレッドは_beginthreadexで始まりました。ps。アプリ内で同じ静的オブジェクトをインスタンス化すると、アプリは重大な問題なしに閉じます。

_endtreadexがデッドロックを引き起こす理由はありますか?それを回避する方法は?

4

1 に答える 1

8

この特定のケースは簡単に説明できます。_endthreadex呼び出しには、DLL_THREAD_DETACHを使用してDllMainを呼び出すことができるように、ローダーロックが必要です。ただし、DLL_PROCESS_DETACHを使用したDllMainの呼び出しの途中であるため、FreeLibraryを呼び出したスレッドはすでにローダーロックを保持しています。

これが壊れる可能性のあるもう1つの方法は、ライブラリを明示的にアンロードせずにプロセスが終了すると、DLL_PROCESS_DETACH呼び出しの前にオブザーバースレッドが終了するため、終了するように通知しようとしても、実行されていないために応答しないことです。もう。

最善のアプローチは、ユーザーが呼び出すための明示的なInitializeLibrary()関数とUninitializeLibrary()関数を作成することです。

于 2012-05-04T02:28:06.740 に答える