Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2015-12

changes in TThread.OnTerminate in fcp-3.0?

9 messages · 4 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Luca Olivetti

Hello,

in a couple of programs I'm using this idiom:

FMyThread:=TMyTread.Create;
FMyThread.FreeOnTerminate:=false;
procedure TMyForm.MyThreadTerminate(Sender:TObject);
begin
   //do something with FMyThread then
   FreeAndNil(FMyThread);
end;

With fpc 2.6.4 it worked flawlessly, with fpc 3.0 sometimes it causes a sigsev somewhere inside CheckSynchronize.

I could find nothing here
http://wiki.freepascal.org/User_Changes_3.0
related to this.
I realize that's an implementation detail so probably what I did was wrong (was it?).
What are the possible solutions (apart from omitting the call to FreeAndNil and setting FreeOnTerminate to true)?

Bye

Luca

Reply by email

Sven Barth
to Luca Olivetti
"Luca Olivetti" wrote 18 lines
Hello, in a couple of programs I'm using this idiom: FMyThread:=TMyTread.Create; FMyThread.FreeOnTerminate:=false; procedure TMyForm.MyThreadTerminate(Sender:TObject); begin //do something with FMyThread then FreeAndNil(FMyThread); end; With fpc 2.6.4 it worked flawlessly, with fpc 3.0 sometimes it causes a

sigsev somewhere inside CheckSynchronize.

Show quoted text 5 lines
I could find nothing here http://wiki.freepascal.org/User_Changes_3.0 related to this. I realize that's an implementation detail so probably what I did was

wrong (was it?).

I'd need to check what the RTL does after OnTerminate is called, but it could be that this worked by chance...

What are the possible solutions (apart from omitting the call to

FreeAndNil and setting FreeOnTerminate to true)?

That would be the safest solution (you can set FMyThread to Nil however inside that handler).

Regards,
Sven

Reply by email

Henry Vermaak
to Luca Olivetti: in a couple of programs I'm using this idiom: FMyThread:=TMyTread.Create;…
Luca Olivetti wrote 14 lines
Hello, in a couple of programs I'm using this idiom: FMyThread:=TMyTread.Create; FMyThread.FreeOnTerminate:=false; procedure TMyForm.MyThreadTerminate(Sender:TObject); begin //do something with FMyThread then FreeAndNil(FMyThread); end;

This is why FreeOnTerminate exists. Set that to True and set FMyThread to nil here, and the thread will free itself after this function returns.

Henry

Reply by email

Luca Olivetti
to Sven Barth: sigsev somewhere inside CheckSynchronize. wrong (was it?). I'd need to check what the RTL…

El 10/12/15 a les 11:13, Sven Barth ha escrit:

Show quoted text 30 lines
Am 10.12.2015 11:05 schrieb "Luca Olivetti" < >: > > Hello, > > in a couple of programs I'm using this idiom: > > > FMyThread:=TMyTread.Create; > FMyThread.FreeOnTerminate:=false; > > > procedure TMyForm.MyThreadTerminate(Sender:TObject); > begin > //do something with FMyThread then > FreeAndNil(FMyThread); > end; > > > With fpc 2.6.4 it worked flawlessly, with fpc 3.0 sometimes it causes a sigsev somewhere inside CheckSynchronize. > > I could find nothing here > http://wiki.freepascal.org/User_Changes_3.0 > related to this. > I realize that's an implementation detail so probably what I did was wrong (was it?). I'd need to check what the RTL does after OnTerminate is called, but it could be that this worked by chance...

Yes and no: OnTerminate is called via Synchronize. In 2.6.4 there could be only one outstanding synchronized method and CheckSynchronize wouldn't access the thread after calling it, so freeing the thread inside OnTerminate was no problem.

Now it's been changed to use a queue of waiting methods, and CheckSynchronize, after calling the method, calls

RtlEnventSetEvent(tmpentry^.SyncEvent)

where SyncEvent is a member of the thread, and if the thread has already been freed that's going to bomb.

It's obvious that you cannot free the thread from inside a "normal" Synchronize call, it's no so obvious you cannot do it in the OnTerminate method, so maybe a note could be added in

http://wiki.freepascal.org/User_Changes_3.0

The new implementation is clearly better....once you know *not* to free the thread inside OnTerminate.

Bye

Luca

Reply by email

Anthony Walter
to Luca Olivetti

I use a four method pattern with threads, while reusing the same thread class everywhere.

1) define a status method to update your user interface based on feedback from the thread
2) define a terminate method to do clean up when a thread finishes
3) define a work method where the thread does its execution
4) define a method which starts the thread feeding it all three methods above

procedure TReplaceForm.ThreadStatus(Sender: TObject);
begin
  Caption := FThread.Status;
end;
procedure TReplaceForm.ThreadTerminate(Sender: TObject);
begin
  FThread := nil;
end;
procedure TReplaceForm.ThreadExecute(Thread: TSimpleThread);
begin
  Thread.Status := 'Step 1';
  Sleep(1000);
  Thread.Status := 'Step 2';
  Sleep(1000);
end;
procedure TReplaceForm.ReplaceButtonClick(Sender: TObject);
begin
  if FThread = nil then
    FThread := TSimpleThread.Create(ThreadExecute, ThreadStatus,
ThreadTerminate);
end;
And done. You never have to define your own TThread derived class again.

Reply by email

Sven Barth
to Luca Olivetti: El 10/12/15 a les 11:13, Sven Barth ha escrit: Yes and no: OnTerminate is called via…
"Luca Olivetti" wrote
It's obvious that you cannot free the thread from inside a "normal"

Synchronize call, it's no so obvious you cannot do it in the OnTerminate method, so maybe a note could be added in

http://wiki.freepascal.org/User_Changes_3.0 The new implementation is clearly better....once you know *not* to free

the thread inside OnTerminate.

In all honesty it was never documented either that you *can* free the object from within OnTerminate and in other occurrences you wouldn't free the object that invoked the handler either, right? So why for TThread then? => no need to mention as a change

Regards,
Sven

Reply by email

Henry Vermaak
to Sven Barth
Sven Barth wrote 15 lines
Am 10.12.2015 12:15 schrieb "Luca Olivetti" : > It's obvious that you cannot free the thread from inside a "normal" Synchronize call, it's no so obvious you cannot do it in the OnTerminate method, so maybe a note could be added in > > http://wiki.freepascal.org/User_Changes_3.0 > > The new implementation is clearly better....once you know *not* to > free the thread inside OnTerminate. In all honesty it was never documented either that you *can* free the object from within OnTerminate and in other occurrences you wouldn't free the object that invoked the handler either, right? So why for TThread then? => no need to mention as a change

Is it worthwhile mentioning that OnTerminate gets called with Synchronize()? I had to dig into the source to verify this.

Henry

Reply by email

Sven Barth
to Henry Vermaak
"Henry Vermaak" wrote 20 lines
On Thu, Dec 10, 2015 at 02:49:50PM +0100, Sven Barth wrote: > Am 10.12.2015 12:15 schrieb "Luca Olivetti" : > > It's obvious that you cannot free the thread from inside a "normal" > Synchronize call, it's no so obvious you cannot do it in the > OnTerminate method, so maybe a note could be added in > > > > http://wiki.freepascal.org/User_Changes_3.0 > > > > The new implementation is clearly better....once you know *not* to > > free > the thread inside OnTerminate. > > In all honesty it was never documented either that you *can* free the > object from within OnTerminate and in other occurrences you wouldn't > free the object that invoked the handler either, right? So why for > TThread then? => no need to mention as a change Is it worthwhile mentioning that OnTerminate gets called with Synchronize()? I had to dig into the source to verify this.

That would indeed be worth mentioning, but that would belong in the documentation then. Would you file a bug report, please?

Regards,
Sven

Reply by email