私のプロジェクトにステートフルなISAPI拡張を作成する必要がありました。 TSessionList =クラス(TObject)に含まれるTSessionオブジェクトを作成しました。期限切れのセッションをクリーンアップするために、定期的にTSessionListをスキャンし、期限切れのセッションをすべて解放するクリーンアップスレッド(TThread子孫)を作成しました。ISAPI拡張TerminateExtensionスレッドデッドロック
私は、dprメイン実行ブロックにTSessionListとCleanupThreadを作成します。それはまあまあです。しかし、実際に私は、CleanupThreadの破壊をどこに置くべきかわかりません。ドキュメントから、ISAPI拡張機能は、拡張機能がアンロードされる直前に呼び出されるTerminateExtensionをエクスポートする必要があることがわかりました。コースのデフォルトのDelphi ISAPI拡張は、そのような関数をエクスポートします。だから私は "overriden it" =私のセッションオブジェクトを解放し、次にデフォルトのISAPIAPP.TerminateExtensionProcを呼び出すTerminateExtensionをエクスポートしました。
ここでは次のように、それがどのように見えるかです:CleanupThread破壊がDoneSessionsで、このように行われている
function TerminateExtension(dwFlags: DWORD): BOOL; stdcall;
begin
DoneSessions;
Result:= ISAPIApp.TerminateExtension(dwFlags);
end;
exports
GetExtensionVersion,
HttpExtensionProc,
TerminateExtension;
begin
CoInitFlags := COINIT_MULTITHREADED;
Application.Initialize;
InitSessions;
Application.CreateForm(TSOAPWebModule, SOAPWebModule);
Application.Run;
end.
:
begin
CleanupThread.Free;
SessionList.Free;
end;
CleanupThreadはのTThreadの簡単な子孫であるので、何のために見ていませんその破壊コードに特有のものです。
問題は、TerminateExtensionがCleanupThread.Freeでフリーズすることです。さらにデバッグすると、TThread.WaitForでフリーズが発生することがわかりました。私はある種のスレッドデッドロック= ISAPIワーカースレッドが私の拡張機能が終了するのを待っている必要があると思われます。これはTThread.WaitForで待機し、メインスレッドがシグナルを出すのを待ちます。
私はこの状況を克服してCleanupThread.Terminateを呼び出し、直接WaitForSingleObject(またはMultiple ???)を使用して最後に解放することができます。しかし、それはちょっと聞こえる...非標準です。
私の質問は:どのようにすればいいですか?スレッドデッドロックを避けるために、ISAPI拡張のサポートスレッドをフリーズ(Terminate - WaitFor - Destroy)する必要がありますか?
ところで、私はすでに標準DLLで同じものを見つけました。任意のthread.WaitForをdllアンロードプロシージャに置くと、メインアプリケーションはライブラリアンロード時にフリーズします。うまくいけば、同じ質問/答えがここに適用されます。