LCL: Fix endless loop in ReleaseComponent (invoking itself via WM_NULL). Issue #40183

Change to only re-invoke ReleaseComponent if any component actually reached a ref-count of 0.
If Components are re-added after a crash during destroying one of them, then they (may or may not) re-invoke immediately. But excluding the crashed one, so there is work to continue.
This commit is contained in:
Martin 2023-04-02 20:33:48 +02:00
parent 54d8f2bdb1
commit 0d415cb235
3 changed files with 19 additions and 2 deletions

View File

@ -1523,6 +1523,7 @@ type
procedure DoIdleActions;
procedure MenuPopupHandler(Sender: TObject);
procedure ProcessAsyncCallQueue;
procedure DoDecLCLRefcountToZero(Sender: TObject);
procedure FreeComponent(Data: PtrInt);
procedure ReleaseComponents;
procedure DoBeforeFinalization;

View File

@ -135,6 +135,7 @@ begin
if Assigned(FOnDestroy) then FOnDestroy(Self);
ProcessAsyncCallQueue;
OnDecLCLRefcountToZero := nil;
if OnMenuPopupHandler=@MenuPopupHandler then
OnMenuPopupHandler:=nil;
@ -2331,6 +2332,12 @@ begin
end;
end;
procedure TApplication.DoDecLCLRefcountToZero(Sender: TObject);
begin
OnDecLCLRefcountToZero := nil;
QueueAsyncCall(@FreeComponent, 0);
end;
procedure TApplication.FreeComponent(Data: PtrInt);
begin
if Data<>0 then
@ -2401,8 +2408,12 @@ begin
exit;
FComponentsToRelease.Add(AComponent);
AComponent.FreeNotification(Self);
if IsFirstItem then
QueueAsyncCall(@FreeComponent, 0);
if IsFirstItem then begin
if TLCLComponent(AComponent).LCLRefCount>0 then
OnDecLCLRefcountToZero := @DoDecLCLRefcountToZero
else
QueueAsyncCall(@FreeComponent, 0);
end;
end;
end;

View File

@ -85,6 +85,9 @@ type
property ReferenceAllocated: Boolean read GetReferenceAllocated;
end;
var
OnDecLCLRefcountToZero: TNotifyEvent;
implementation
uses
@ -180,6 +183,8 @@ end;
procedure TLCLComponent.DecLCLRefCount;
begin
dec(FLCLRefCount);
if (FLCLRefCount <= 0) and (OnDecLCLRefcountToZero <> nil) then
OnDecLCLRefcountToZero(Self);
end;
{ TLCLReferenceComponent }