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
chore: keep references to active menus to prevent gc #19427
chore: keep references to active menus to prevent gc #19427
Conversation
Without this such menus would be destroyed by js garbage collector even when they are still displayed.
@CezaryKulakowski thanks for this! Before we review it, would you please fill out the template properly with a more complete description, a filled template, and Release Notes as described in the template comment? We'll be able to review more effectively once that has been completed. |
@codebytere please let me know if updated description is sufficient :). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree that menus definitely shouldn't be gc-able while open, and it's probably not the best idea to tell users to retain the reference globally, so I think this is the best solution for now.
cc @MarshallOfSound for second 💭
(failure is expected for forks, i'll go away if this PR is rebased though it's not necessary to do prior to merge)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approving based on @deepak1556 's conclusion this won't leak 👍
Coming back to the original problem outlined, I would say the current behavior expecting a global reference for menu aligns with what we expect for BrowserWindow. These are objects that are meant to be maintained for the lifetime of the app or however the user decides in the main process, tying it to a particular scope would be difficult. Being explicit about this behavior is fine IMO.
@CezaryKulakowski this sounds like a good thing to have. /cc @zcbenz who wrote the original implementation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Blocking to get consensus
It is hard to make things still work correctly when |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm good with current solution.
Release Notes Persisted
|
/trop run backport-to 7-1-x,6-1-x |
The backport process for this PR has been manually initiated - |
The backport process for this PR has been manually initiated - |
I was unable to backport this PR to "7-1-x" cleanly; |
I was unable to backport this PR to "6-1-x" cleanly; |
@CezaryKulakowski could you potentially backport this to the above branches? I can try to get to it if not |
@codebytere I will take care of this today or on Monday. |
I've checked that this issue doesn't reproduce either on 6-1-x or 7-1-x. @codebytere do you have another test case for this? |
@CezaryKulakowski the original issue was opened for 6 though? either way i think we should backport for safety's sake. I'll handle it. |
@codebytere has manually backported this PR to "7-1-x", please check out #22151 |
@codebytere has manually backported this PR to "6-1-x", please check out #22152 |
Fixes #19424.
How to reproduce
Launch this simple application:
After it's started press arrow down to cycle through both menu's entries.
Expected behavior
Nothing bad happens.
Actual behavior
After few seconds - when js's garbage collector is started - menu is being destroyed. Additionaly crash may occur (~50% reproducibility rate).
As object
menu
is not kept as global reference in js garbage collector destroys it. It's a matter of debate if that's correct behaviour (on one side object is "local" on js side but on the other menu is active and displayed). The bigger issue is that js object is being destroyed while c++ object is still alive and active. If user interacts with it (like changing focus of current element) when js object is already destroyed crash in v8 will occur. We get notification on c++ side that js object was destroyed by callback but the problem is that - by design - all instances of classWrappableBase
, likeMenu
, are destroyed in two steps: firstWrappableBase::FirstWeakCallback
is called where we clear wrapper to js object, and after thatWrappableBase::SecondWeakCallback
is called where we destroy c++ object. Crash occurs when there is any call to Menu (likeMenu::GetAcceleratorTextAt
after focused element was changed) after first callback but before second callback was called.With proposed fix we keep references to all currently displayed menus so garbage collector doesn't destroy active menus. If we decide that this is expected behaviour that popup can be destroyed by js garbage collector even when it's still displayed the solution would be to check if
GetWrapper()
doesn't return empty object in all calls in classMenu
(e.g.Menu::IsCommandIdChecked
,Menu::GetAcceleratorTextAt
,Menu::IsCommandIdEnabled
...).notes: Don't destroy active menus created as local objects in javascript