Watch, Follow, &
Connect with Us
Public Report
Report From: Delphi-BCB/RTL/Delphi/Thread support    [ Add a report in this area ]  
Report #:  71230   Status: Open
Crash if using exception in TThread.OnTerminate handler
Project:  Delphi Build #:  11.0.2902.10471
Version:    11.0 Submitted By:   Yuri Pavlov
Report Type:  Crash / Data loss / Total failure Date Reported:  2/6/2009 6:38:03 AM
Severity:    Commonly encountered problem Last Updated: 3/20/2012 2:24:39 AM
Platform:    All versions Internal Tracking #:   267991
Resolution: None (Resolution Comments) Resolved in Build: : None
Duplicate of:  None
Voting and Rating
Overall Rating: No Ratings Yet
0.00 out of 5
Total Votes: None
Description
unit Unit3;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm3 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    procedure OnThreadTerminate(Sender: TObject);
  end;

  TErrorThread = class(TThread)
  public
    procedure Execute; override;
  end;

var
  Form3: TForm3;

implementation

{$R *.dfm}

procedure TForm3.Button1Click(Sender: TObject);
begin
  With TErrorThread.Create(True) do
    begin
      FreeOnTerminate := True;
      OnTerminate := OnThreadTerminate;
      Resume;
    end;
end;

procedure TForm3.OnThreadTerminate(Sender: TObject);
begin
  Raise Exception.Create('Raise some exception');
end;

{ TErrorThread }

procedure TErrorThread.Execute;
begin
//Do nothing
end;

end.
Steps to Reproduce:
None
Workarounds
None
Attachment
None
Comments

Alexey Beloborodov at 8/16/2009 7:00:46 AM -
OnTerminate works via Synchronize. Inside Execute exceptions in synchronized procedure work well, but inside OnTerminate something goes wrong. The differences is try/except block around Execute and absence of such block around OnTerminate:

function ThreadProc(Thread: TThread): Integer;
...
begin
...
  try
    if not Thread.Terminated then
    try         // <<<
      Thread.Execute;
    except
      Thread.FFatalException := AcquireExceptionObject;
    end;
  finally
...
    Thread.DoTerminate;  // <<<
...

procedure TThread.DoTerminate;
begin
  if Assigned(FOnTerminate) then Synchronize(CallOnTerminate);
end;

procedure TThread.CallOnTerminate;
begin
  if Assigned(FOnTerminate) then FOnTerminate(Self);
end;

(BTW I have no idea if this legal at all to raise exception in finally block.)

Server Response from: ETNACODE01