Fix crashes related to TabWidget::removeTab() that were reported by #1029 #1030
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Thanks for submitting a pull request! Please provide enough information so that others can review your pull request. Additionally, make sure you've done all of these things:
PR Description
What type of PR is this? (Check one of the boxes below)
What does this pull request do?
Fix crashes related to TabWidget::removeTab() that were reported by #1029
Have you tested your changes (if applicable)? If so, how?
Yes. I've verified locally that the crashes mentioned in #1029 no longer occur. I also successfully built the Windows installer and verified that all the tests still pass and this build does not crash with the bug repro.
Futher details of this pull request
This fix is primarily just dealing with use-after-free issues. PyPanel objects would register themselves in their constructor, but never unregistered on destruction. This was causing code like the loop in PanelWidget::takeClickFocus() to make calls on PyPanel object pointers that were already destroyed.
Some crashes were also caused by TabWidget::removeTab() trying to call w->setVisible(false) on objects that have already been destroyed. This can happen when the removeTabToPython() call, that removes the reference to the panel on the app.pane2 object, causes the PyPanel object to actually be destroyed. This happens when the Python code does not keep another reference to the panel when it makes a call to remove the tab. The fix for this was to simply return right after the removeTabToPython() call in the PyPanel case. This avoids the crash and skips a bunch of code that doesn't appear to apply to the PyPanel case.
I updated the docs for removeTab() to make it a little clearer that the tab object can be destroyed within the call if it is the last reference.