Ich musste StateAPI-Erweiterung für mein Projekt erstellen. Ich habe erfolgreich ein TSession-Objekt erstellt, das in einer TSessionList = class (TObject) enthalten ist. Zur Bereinigung abgelaufener Sitzungen habe ich einen Aufräum-Thread (TThread-Nachfolger) erstellt, der TSessionList regelmäßig überprüft und alle abgelaufenen Sitzungen freigibt.ISAPI Extension TerminateExtension Thread Deadlock
Ich erstelle die TSessionList und die CleanupThread im Hauptausführungsblock dpr. Was gut ist. Aber eigentlich bin ich mir nicht sicher, wo ich die Zerstörung von CleanupThread hinlegen soll. Aus der Dokumentation habe ich festgestellt, dass die ISAPI-Erweiterung TerminateExtension exportieren muss, die unmittelbar vor dem Entladen der Erweiterung aufgerufen wird. Die standardmäßige Delphi-ISAPI-Erweiterung exportiert natürlich eine solche Funktion. Also habe ich es "überschrieben" = exportierte meine TerminateExtension, die meine Sitzungsobjekte freigibt und dann den Standard ISAPIAPP.TerminateExtensionProc aufruft.
Hier ist, wie es aussieht:
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.
Die CleanupThread Zerstörung wird in DoneSessions diese Weise getan:
begin
CleanupThread.Free;
SessionList.Free;
end;
Die CleanupThread ist einfach Nachkomme TThread, so schauen Sie nicht für alles spezifisch in seinem Zerstörungscode.
Das Problem ist, dass die TerminateExtension nur in CleanupThread.Free einfriert. Weiter Debuggen fand ich, dass das Einfrieren im TThread.WaitFor passiert. Ich vermute, dass es eine Art Thread-Deadlock geben muss = ISAPI-Worker-Thread wartet auf die Beendigung meiner Erweiterung, die in TThread.WaitFor wartet, damit der Haupt-Thread signalisiert wird (oder was auch immer).
Ich weiß, ich könnte diese Situation zu überwinden, CleanupThread.Terminate aufrufen, dann direkte WaitForSingleObject (oder Multiple ???) und schließlich befreien. Aber das klingt ein bisschen ... nicht standardgemäß.
Daher ist meine Frage: Wie und wann sollte ich Free (Beenden - WaitFor - Destroy) Support-Threads in ISAPI-Erweiterung, Thread-Deadlock zu vermeiden?
BTW: Ich habe bereits das gleiche in der Standard-DLL gefunden. Wenn Sie thread.WaitFor in den Dll Unload-Prozess setzen, friert Ihre Haupt-App nur beim Entladen der Bibliothek ein. Also die gleiche Frage/Antwort gilt hoffentlich hier.