TThread.Synchronize uses global lock and variables
Original Reporter info from Mantis: kluug.net @onpok
-
Reporter name: Ondrej Pokorny
Original Reporter info from Mantis: kluug.net @onpok
- Reporter name: Ondrej Pokorny
Description:
TThread.Synchronize uses the following global variables:
{ system independend threading code }
var
{ event that happens when gui thread is done executing the method}
ExecuteEvent: PRtlEvent;
{ event executed by synchronize to wake main thread if it sleeps in CheckSynchronize }
SynchronizeTimeoutEvent: PRtlEvent;
{ guard for synchronization variables }
SynchronizeCritSect: TRtlCriticalSection;
{ method to execute }
SynchronizeMethod: TThreadMethod;
{ should we execute the method? }
DoSynchronizeMethod: boolean;
{ caught exception in gui thread, to be raised in calling thread }
SynchronizeException: Exception;
These variables should not be global but should be defined for every TThread separately.
As a result of global definition, there is a dead-lock when Synchronize is called within a thread that waits for another Synchronize to finish.
Steps to reproduce:
This code works in Delphi just well. In FPC, you get a dead-lock in Synchronize:
type
TMyThread = class(TThread)
private
fCounter: Integer;
fFinished: Boolean;
procedure StartNew;
protected
procedure Execute; override;
public
constructor Create(aCounter: Integer);
property Terminated;
end;
{ TMyThread }
constructor TMyThread.Create(aCounter: Integer);
begin
inherited Create(False);
fCounter := aCounter;
end;
procedure TMyThread.Execute;
begin
Sleep(50);
Synchronize(StartNew);//dead-lock here in 2nd thread
fFinished := True;
end;
procedure TMyThread.StartNew;
var
xThread: TMyThread;
begin
if fCounter < 2 then
begin
xThread := TMyThread.Create(fCounter+1);
xThread.FreeOnTerminate := False;
while not xThread.fFinished do
begin
Application.ProcessMessages;//as a result of the dead-lock, this loop is infinite
end;
xThread.Free;
end;
end;
procedure TestThread;
var
xThread: TThread;
begin
xThread := TMyThread.Create(0);
xThread.FreeOnTerminate := True;
end;
Mantis conversion info:
- Mantis ID: 27628
- Version: 2.6.2
- Fixed in version: 3.0.0
- Fixed in revision: 30153 (#0b52513c)
- Monitored by: » Vincent (Vincent Snijders)
- Target version: 3.0.0