-
Notifications
You must be signed in to change notification settings - Fork 81
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 possible hierarchy corruption during removing ComposePanel
with LayerType.OnComponent
#1132
base: jb-main
Are you sure you want to change the base?
Conversation
17f5197
to
fff3e56
Compare
// [dispose] might trigger hierarchy change for example removing [LayerType.OnComponent] | ||
// layers. That will conflict with removing this [ComposePanel]. To avoid such | ||
// issues we need to call [dispose] after leaving this method. | ||
SwingUtilities.invokeLater { |
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.
Using any dispatching should be the last resort, as it introduces race conditions. One of the race conditions that came to my mind is:
val frame = JFrame()
frame.isVisible = true
val panel = ComposePanel()
frame.add(panel) // addNotify, init scene
frame.remove(panel) // removeNotify, dispatch dispose
frame.add(panel) // reinit scene, leak the old scene
...
// dispose the new scene
We can write a warding code for this race, but let's discuss alternatives first. Do I understand correctly that we have an issue with this hierarchy:
Window
ContentPane
ComposePanel
Layer1 // created/removed by ComposePanel
Layer2 // created/removed by ComposePanel
Do we have a crash or it is incorrect behaviour because of internal AWT state corruption?
Will moving layers into its own container help?
Window
ContentPane
ComposePanel
Layers
Layer1 // created/removed by ComposePanel
Layer2 // created/removed by ComposePanel
Also, worth to write a test, if it's not difficult.
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.
Another alternative - disposing the scene without dispatching, but dispatch removing of the layers if they are removed in removeNotify
(with the same race warding). It will be more safe, and closer to the issue.
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.
Do we have a crash or it is incorrect behaviour because of internal AWT state corruption?
Some kind of. Sometimes it's an out-of-bounds crash, sometimes it just leads to a corrupted state without a crash
Will moving layers into its own container help?
- It's controlled by the user
- Layers (windowContainer) should be logically one of the parents of
ComposePanel
but yes, it will avoid calling remove
inside another remove
call of the same container
Also, worth to write a test, if it's not difficult.
Sure. Initially this PR is a push of not planned fix from local stash with the main intention to discuss the problem. Let me convert it to draft to make it more clear
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.
disposing the scene without dispatching, but dispatch removing of the layers
It was in my head as a variant too
Proposed Changes
dispose
might trigger hierarchy change for example removingLayerType.OnComponent
layers. That will conflict with removing thisComposePanel
. To avoid such issues we need to calldispose
after leaving this method.Testing
Test: remove
ComposePanel
when it has opened layers attached to its parent