Skip to content

Incorrect exception handling if an exception raised in TThread decendant class's constructor.

Summary

Incorrect destructor handling of TThread class, if an exception is raised in TThread based child class prior to calling the inherited constructor.

System Information

  • Operating system: Linux
  • Processor architecture: x86-64
  • Compiler version: 3.2.2
  • Device: Computer

Steps to reproduce

If you raise an exception in a class constructor derived from TThread prior to calling the inherited costructor, then (as we all know) the class destructor of our TThread based class will be called. If you try to call inherited destructor, an EThreadError exception will be raised in a few tries.

Example Project

unit MyUnit;

interface

uses
  Classes, SysUtils;

type
  EMyException = class(Exception);

  TMyThread = class(TThread)
  protected
    procedure Execute; override;
  public
    constructor Create;
    destructor Destroy; override;
  end;

implementation

constructor TMyThread.Create;
begin
  raise EMyException.Create('my error message');
  inherited Create(False);
end;

destructor TMyThread.Destroy;
begin
  inherited;    // <-- EThreadError exception with Runtime Error 236 is raised here.
end;

procedure TMyThread.Execute; 
begin
end;

end.
program MyTest;

uses
  Classes, SysUtils, MyUnit;

var
  x: TMyThread;
  i: Integer;

begin
  for i := 1 to 100 do 
  begin
    try
      x := TMyThread.Create;
    except
      on e: Exception do
        Writeln(e.Message);   // EThreadError with RuntimeError 236 is catch instead of EMyException
    end;
  end;
end.

What is the current bug behavior?

Runtime error 236 with EThreadError exception is raised inside TThread.Destroy

What is the expected (correct) behavior?

No Runtime Errors to happen and EMyException raised and catched inside the sample program.

Relevant logs and/or screenshots

Possible fixes

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information