Thread terminiert nicht

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Thread terminiert nicht

Beitrag von Warf »

Hey ho Leute. Ich habe ein sehr ungewöhnliches Problem. Ich habe ein Programm welches nichts anderes macht als einen Thread zu erstellen, diesen auszuführen und zu warten bis er Terminiert (Der Thread ist gleichzeitig die Logik hinter einem Daemon, und daher möchte ich daran nichts ändern). Code:

Code: Alles auswählen

 
  TTestClass= class
  private
    Core: TTBCore;
    procedure ThreadStopped(Sender: TObject);
  public
    procedure ExecuteThread;
  end;
 
{ TTestClass}
 
procedure TTestClass.ThreadStopped(Sender: TObject);
begin
  if Sender=Core then
    Core:=Nil;
  Sender.Free;
end;
 
procedure TTestClass.ExecuteThread;
begin
  Core:=TTBCore.Create(@ThreadStopped);
  while Assigned(Core) and (not Core.Finished) do Sleep(200);
end;


Der Konstruktor und Destruktor des Threads sieht wie folgt aus:

Code: Alles auswählen

 
constructor TTBCore.Create(AOnTerminate: TNotifyEvent);
begin
  FreeOnTerminate := False;
  OnTerminate := AOnTerminate;
  {$IfDef DEBUG}
  CreateDebugLogger;
  {$Else}
  CreateFileLogger(SLogPath);
  {$EndIf}
 
  inherited Create(False);
end;
 
destructor TTBCore.Destroy;
begin
  DestroyLogger;
  inherited Destroy;
end;


Der einfachheit halber sei der Code der Execute Methode leer (dann tritt der Selbe fehler auf).
Nun obwohl nichts in der Execute ausgeführt wird, wird niemals OnTerminate aufgerufen, und somit auch nicht die Methode ThreadStopped die den Speicher wieder frei räumen soll. Die Frage die ich mir nun Stelle ist, warum nicht?
PS: Ich verwende ein einfaches Programm ohne Forms o.ä. unter Windows 10.
PPS: Wenn ich FreeOnTerminate auf True setze wird der Thread dennoch auch nicht gefreed.

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Thread terminiert nicht

Beitrag von Michl »

Hier geht es. Eben probiert:

Code: Alles auswählen

program project1;
 
uses Classes;
 
type
 
  { TTBCore }
 
  TTBCore = class(TThread)
  protected
    procedure Execute; override;
  public
    constructor Create(AOnTerminate: TNotifyEvent);
  end;
 
  { TTestClass }
 
  TTestClass= class
  private
    Core: TTBCore;
    procedure ThreadStopped(Sender: TObject);
  public
    constructor Create;
    procedure ExecuteThread;
  end;
 
{ TTestClass }
 
procedure TTestClass.ThreadStopped(Sender: TObject);
begin
  writeln('TTestClass.ThreadStopped ');
  if Sender = Core then
    Core := nil;
  Sender.Free;
end;
 
constructor TTestClass.Create;
begin
  Core := nil;
end;
 
procedure TTestClass.ExecuteThread;
begin
  writeln('TTestClass.ExecuteThread ');
  Core := TTBCore.Create(@ThreadStopped);
end;
 
{ TTBCore }
 
procedure TTBCore.Execute;
begin
  writeln('TTBCore.Execute ');
  Sleep(100);
end;
 
constructor TTBCore.Create(AOnTerminate: TNotifyEvent);
begin
  FreeOnTerminate := False;
  OnTerminate := AOnTerminate;
  inherited Create(False);
end;
 
var
  aTest: TTestClass;
 
begin
  aTest := TTestClass.Create;
  repeat
    if not Assigned(aTest.Core) then
      aTest.ExecuteThread;
    CheckSynchronize;
  until not Assigned(aTest.Core);
  aTest.Free;
end.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Thread terminiert nicht

Beitrag von Warf »

Das funktioniert bei mir auch. Der Thread funktioniert als Daemon auch super, nur in meinem Projekt will es nicht ganz.

Das resultat sind damit natürlich memory leaks, allerdings werde ich daraus auch nicht schlau

Code: Alles auswählen

Heap dump by heaptrc unit
459 memory blocks allocated : 34347/35208
456 memory blocks freed     : 34279/35128
3 unfreed memory blocks : 68
True heap size : 491520
True free heap : 491072
Should be : 491248
Call trace for block $01813428 size 28
  $00570EAE
  $00559515
  $0040EFB4
  $BAADF00D
  $BAADF00D
  $BAADF00D
  $BAADF00D
  $BAADF00D
Call trace for block $0180D8C0 size 12
  $00559515
  $0040EFB4
  $BAADF00D
  $BAADF00D
  $BAADF00D
  $BAADF00D
  $BAADF00D
  $BAADF00D
Call trace for block $018133B8 size 28
  $0044F15C
  $0040EFB4
  $004487AD
  $0040EFB4
  $0045478A
  $004D9031
  $004E286D
  $BAADF00D

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Thread terminiert nicht

Beitrag von Socke »

Warf hat geschrieben:Das funktioniert bei mir auch. Der Thread funktioniert als Daemon auch super, nur in meinem Projekt will es nicht ganz.

Das resultat sind damit natürlich memory leaks, allerdings werde ich daraus auch nicht schlau


$BAADF00D weist auf nicht initialisierten Speicher hin: https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_debug_values
Du hast in deinem Programm also noch ein paar Fehler.

Kannst du ein Minimalbeispiel erstellen, in dem der Fehler auftritt?
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Thread terminiert nicht

Beitrag von Warf »

Socke hat geschrieben:
Warf hat geschrieben:Das funktioniert bei mir auch. Der Thread funktioniert als Daemon auch super, nur in meinem Projekt will es nicht ganz.

Das resultat sind damit natürlich memory leaks, allerdings werde ich daraus auch nicht schlau


$BAADF00D weist auf nicht initialisierten Speicher hin: https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_debug_values
Du hast in deinem Programm also noch ein paar Fehler.

Kannst du ein Minimalbeispiel erstellen, in dem der Fehler auftritt?


Hab rausgefunden was den Fehler auslöst. Ich habe mir eine Logger Unit geschrieben, welche im Debug Modus in StdOut schreibt, das Problem war das ich dafür eine Variable vom typ Text verwendet habe und einfach LogFile := StdOut, und der Thread anscheinend nicht Terminieren konnte solange StdOut offen war. Arbeite jetzt mit File Handles und damit wäre das geklärt. Das Problem mit diesen Memory Leaks ist aber ein anderes, ich versuche mal rauszufinden wo das herkommt

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Thread terminiert nicht

Beitrag von Warf »

Habe jetzt mal dem anderen Problem auf den Zahn gefühlt, es liegt an Indy. Dieses Programm:

Code: Alles auswählen

program Minimal;
 
uses heaptrc, IdTelnet;
 
begin
  SetHeapTraceOutput('heap.trc');
end.
 
 


Wirft diesen Heaptrace output

Code: Alles auswählen

Heap dump by heaptrc unit
70 memory blocks allocated : 1669/1808
67 memory blocks freed     : 1601/1728
3 unfreed memory blocks : 68
True heap size : 262144 (112 used in System startup)
True free heap : 261712
Should be : 261760
Call trace for block $017335F8 size 28
  $00444E0E  TIDTHREADSAFE__CREATE,  line 253 of ./Core/IdThreadSafe.pas
  $00426185  IDTHREAD_$$_init,  line 730 of ./Core/IdThread.pas
  $0040A8B4
  $BAADF00D
  $BAADF00D
  $BAADF00D
  $BAADF00D
  $BAADF00D
Call trace for block $0172C910 size 12
  $00426185  IDTHREAD_$$_init,  line 730 of ./Core/IdThread.pas
  $0040A8B4
  $BAADF00D
  $BAADF00D
  $BAADF00D
  $BAADF00D
  $BAADF00D
  $BAADF00D
Call trace for block $01733588 size 28
  $0042565C  IDSTACK_$$_init,  line 1213 of ./System/IdStack.pas
  $0040A8B4
  $BAADF00D
  $BAADF00D
  $BAADF00D
  $BAADF00D
  $BAADF00D
  $BAADF00D
 


Und nach ein wenig einlesen schaut es so aus als wäre dieses Memory leak erwartet

Antworten