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 DoIdleActions;
procedure MenuPopupHandler(Sender: TObject); procedure MenuPopupHandler(Sender: TObject);
procedure ProcessAsyncCallQueue; procedure ProcessAsyncCallQueue;
procedure DoDecLCLRefcountToZero(Sender: TObject);
procedure FreeComponent(Data: PtrInt); procedure FreeComponent(Data: PtrInt);
procedure ReleaseComponents; procedure ReleaseComponents;
procedure DoBeforeFinalization; procedure DoBeforeFinalization;

View File

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

View File

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