Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix ToolStrip memory leak due to MouseHoverTimer and #4808 #11358

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

kirsan31
Copy link
Contributor

@kirsan31 kirsan31 commented May 11, 2024

Fix #4808 and problem that was mentioned in #11334.

Proposed changes

Replace ToolStripItem? _currentItem with WeakReference<ToolStripItem?> _currentItem in MouseHoverTimer
Implement this suggestion.

Customer Impact

No more memory leak if ToolStripItem will be disposed after MouseHoverTimer start.
No more memory leak of chilled elements due to DisplayedItems and OverflowItems collections..

Regression?

  • No

Risk

Minimal.

Screenshots

ToolStripItem below was disposed, but remain in memory:
timer1
timer2

Test methodology

Microsoft Reviewers: Open in CodeFlow

@kirsan31 kirsan31 requested a review from a team as a code owner May 11, 2024 10:12
Copy link

codecov bot commented May 11, 2024

Codecov Report

Attention: Patch coverage is 98.57143% with 1 lines in your changes are missing coverage. Please review.

Project coverage is 74.27562%. Comparing base (4095304) to head (e109957).
Report is 11 commits behind head on main.

Additional details and impacted files
@@                 Coverage Diff                 @@
##                main      #11358         +/-   ##
===================================================
+ Coverage   74.24289%   74.27562%   +0.03273%     
===================================================
  Files           3022        3025          +3     
  Lines         626297      626919        +622     
  Branches       46702       46750         +48     
===================================================
+ Hits          464981      465648        +667     
+ Misses        157921      157909         -12     
+ Partials        3395        3362         -33     
Flag Coverage Δ
Debug 74.27562% <98.57143%> (+0.03273%) ⬆️
integration 18.00034% <90.00000%> (-0.26493%) ⬇️
production 47.00213% <95.00000%> (+0.08707%) ⬆️
test 96.99459% <100.00000%> (-0.04183%) ⬇️
unit 43.99688% <95.00000%> (+0.14972%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

@kirsan31 kirsan31 changed the title Fix ToolStrip memory leak due to MouseHoverTimer. Fix ToolStrip memory leak due to MouseHoverTimer and #4808 May 12, 2024
@kirsan31
Copy link
Contributor Author

Added commit that fix #4808 (thanks to @elachlan).

@elachlan elachlan added the waiting-review This item is waiting on review by one or more members of team label May 12, 2024
@elachlan
Copy link
Contributor

@Olina-Zhang Could your team please test this pr to confirm the issues are resolved?

@Olina-Zhang
Copy link
Member

@Olina-Zhang Could your team please test this pr to confirm the issues are resolved?

@elachlan @kirsan31 Tested this PR, just can confirm that GH issue #4808 is fixed, I am not clear how to verify #11334, can you give some more information about how to repro it?

@kirsan31
Copy link
Contributor Author

kirsan31 commented May 14, 2024

@Olina-Zhang

can you give some more information about how to repro it?

Same repro app, the key is to remove item immediately after MouseHoverTimer has started. So simply hover and immediately click:

timer.mp4

image

@Olina-Zhang
Copy link
Member

@kirsan31 thanks for your info.
Adding the GH issue #11334 validation: fixed
image

{
// To prevent memory leaks when item removed from main collection,
// we need to remove it from _displayedItems and _overflowItems too.
_displayedItems?.Remove(item);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to make _displayedItems and _overflowItems collections of weak references instead?

I wonder if we have cases when item is removed but is not disposed and will be reused.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to make _displayedItems and _overflowItems collections of weak references instead?

That was the first thing I thought of. But there about 100 references, it will be too overcomplicated...

I wonder if we have cases when item is removed but is not disposed and will be reused.

Both collections insertions appears only in SetDisplayedItems and both are cleared at start of the method:

protected virtual void SetDisplayedItems()
{
DisplayedItems.Clear();
OverflowItems.Clear();
HasVisibleItems = false;

So, the logic must preserve.

Also. SetDisplayedItems are called from OnLayout and both ToolStripItemCollection.Insert and ToolStripItemCollection.Add are calling OnItemAdded -> DoLayoutIfHandleCreated -> ... SetDisplayedItems.

P.s. I noticed a strange difference in the ToolStripItemCollection.Insert and ToolStripItemCollection.Add methods:

if (_itemsCollection && _owner is not null)
{
_owner.OnItemAddedInternal(value);
_owner.OnItemAdded(new ToolStripItemEventArgs(value));
}

if (_itemsCollection && _owner is not null)
{
if (_owner.IsHandleCreated)
{
LayoutTransaction.DoLayout(_owner, value, PropertyNames.Parent);
}
else
{
// next time we fetch the preferred size, recalc it.
CommonProperties.xClearPreferredSizeCache(_owner);
}
_owner.OnItemAddedInternal(value);
_owner.OnItemAdded(new ToolStripItemEventArgs(value));
}

this code is not present in ToolStripItemCollection.Add:

if (_owner.IsHandleCreated) 
{ 
   LayoutTransaction.DoLayout(_owner, value, PropertyNames.Parent); 
} 
else 
{ 
   // next time we fetch the preferred size, recalc it. 
   CommonProperties.xClearPreferredSizeCache(_owner); 
} 

🤔

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we own all items in these collections?

Copy link
Contributor Author

@kirsan31 kirsan31 May 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we own all items in these collections?

No of course. More of it I doubt that we own any of them. These are menu items. But all additions of these elements are of course only ours (in SetDisplayedItems), as I wrote above.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep in mind that we are removing the ToolStripItem from our collections here and not disposing of them. So we free up the references, but aren't responsible for the lifetime.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
waiting-review This item is waiting on review by one or more members of team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ToolStripMenuItem can lead to memory leaks
4 participants