chubbson - Mi 27.01.10 13:50
Titel: Thread Debug problem in DLL aufruf
Hallo
Ich habe ein problem mit Threads in einer DLL.
Ich starte mit einem LoadLib der mir meine DLL ladet eine Funktion aus der DLL die mir
~5 Threads in einem Threadpool laded und ausführen lässt.
Wenn ich über ein Abort die Threads beende werden alle threads solange im threadpool
geprüft bis diese beendet werden können. Sobald alle Threads beendet sind
ist der abort abgeschlossen. Soweit funktioniert alles einwandfrei.
Nun wenn ich die DLL aber lade und starte wieder alle 5 Threads am laufen sind und ich dann
direkt eine FreeLibrary ausführe, wird zwar die abort funktion ausgeführt die dann für
alle 5 threads ein terminate ausführt. danach werden alle 5 threads so lange geprüft nicht mit waitfor
sondern ende execute wird ein property isExecuted auf true gesetzt.
naja danach werden alle 5 threads so lange geloopt bis alle auf true sind.
Hier in dieser Schleife bleibt er manchal in einem Deadlock da irgendiwie nicht mehr alle Threads ausführen kann. sprich es sind noch nicht alle auf Excecuted und wenn ich den Breakpoint nur im Worker habe breakt er dort auch nicht mehr. aber der prozessor arbeitet weiterhin auf hochtouren.
Manchmal wird die isExecuted in einigen Threads auch auf true gesetzt obwohl ich einen breakpoint auf dem einzigen Aufruf habe ohne das er bei diesem breakpoint haltet.
Kann mir da jemand weiterhelfen. der Debugger müsste doch bei jedem thread in der Execute halten oder?
Ich schnippel mir gleich noch einige Code auszüge zusammen
Verwendet wird D7 und die dll wird gedebuggt.
abort funktion die darauf wartet bis alle threads beendet wurden...
die abort funktion läuft einwandfrei wenn man sie direkt aufruft.
Wenn sie über FreeLibrary aufgerufen wird tritt der oben beschriebene fehler auf
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38:
| procedure THandler.Abort(); var worker: TWorker; i: Integer; allTerminated: Boolean; j, p: Integer; begin if (HandlerState <> hsReady) then begin if (Assigned(Threads) and (Threads.Count > 0)) then begin
for i:=Threads.Count-1 downto 0 do begin worker := TWorker(Threads[i]); worker.Terminate(); end;
repeat allTerminated := true; for i:=Threads.Count-1 downto 0 do begin worker := TWorker(Threads[i]); if not worker.IsExecuted then allTerminated := false; end; until (allTerminated);
for i:=Threads.Count-1 downto 0 do begin worker := TWorker(Threads[i]); worker.Free(); Threads.Delete(i); end;
end;
CleanQueue(); HandlerState := hsReady; end; end; |
Der Worker Execute teil des Thread
Mancham kommt der Debuger gar nicht mehr in den Execute teil beim abort über freelibrary
im Try part werden noch funktionen einen anderen DLL aufgerufen! evtl da ein problem?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| procedure TWorker.Execute; begin try try except on E:Exception do begin end; end; finally FIsExecuted := true; end; end; |
Moderiert von
Narses: Topic aus Delphi Language (Object-Pascal) / CLX verschoben am Mi 27.01.2010 um 13:37
Astat - Mi 27.01.10 14:30
chubbson hat folgendes geschrieben : |
Wenn sie über FreeLibrary aufgerufen wird tritt der oben beschriebene fehler auf |
Hallo chubbson, zeig doch mal den Entry der DLL.
Als Klassiker wird im DLL_PROCESS_DETACH mit einem WaitForMultipleObject alles aufgeräumt.
Die Abfrage nach dem Status der Threads in einer Schleife ist da etwas eigenartig.
Normalerweise verwendet man Sperrobjekte zum Signalling, dafür wurden diese gebaut.
lg. Astat
Moderiert von
Narses: Zitat kenntlich gemacht.
chubbson - Mi 27.01.10 16:50
Die DLL debuggen kann ich schon, da liegt nicht das problem.
Mein Problem liegt das wenn ich im Worker am Ende der Execute Procedure ein Breakpoint auf
FIsExecuted := true; setze das der debuger nur sporadisch dort anhält.
Bei manchen Threads wird das Flag Automatisch auf True gesetzt und bei manchen hält er beim Breakpoint.
Das ist es was mich am meisten Iritiert.
Hmm okay ich könnte auch ein sleep in die repeat schleife einbauen. Ich prüfe halt mein eigenes Flag ob dieses gesetzt wurde.
Ich habe nun auch
Delphi-Quelltext
1:
| WaitForMultipleObjects(Threads.Count, @Threads, true, 0 ); |
anstatt der Schleife genommen. Jedoch hält er auch dort nur sporadisch beim worker Breakpoint.
'WaitForMultipleObjects' wird dann relativ schnell verlassen. Die IsExecuted properties sind da aber auch nicht überall auf true gesetzt.
Auch wenn ich die Threads mit Free freigebe, das wird weiter unten sowieso noch gemacht, werden die einzelnen Excecute methoden im Handler bis am schluss abgearbeitet.
Wie gesagt, das Problem habe ich nur wenn ich meine DLL mit FreeLibrary freigebe und dort meine Abort Funktion aufrufe. Wenn ich die Abort funktion zuerst aufrufe und danach erst Free Library funktioniert alles einwandfrei.