Fix use-after-free crash on exit during GLCanvas3D teardown (#14588)

Plater's pImpl (unique_ptr<priv> p) is destroyed before the wxWindow base
destructor runs DestroyChildren(), so child GLCanvas3D windows are torn down
after p is gone. GLCanvas3D::~GLCanvas3D() -> reset_volumes() then dereferences
the freed p through two paths:
  - Selection::clear() -> plater()->canvas3D() -> p->get_current_canvas3D()
  - _set_warning_notification() -> plater()->get_notification_manager()

Guard both with the existing wxGetApp().is_closing() flag; both are UI-only
side effects that are no-ops during shutdown, so normal-use behavior is
unchanged.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Walter Almada
2026-07-13 01:54:42 -05:00
committed by GitHub
parent 72005959d4
commit 5a53d2eb88
2 changed files with 6 additions and 0 deletions

View File

@@ -10289,6 +10289,9 @@ void GLCanvas3D::_set_warning_notification_if_needed(EWarning warning)
void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
{
// Skip on shutdown: Plater's pImpl is already freed, so get_notification_manager() would use-after-free.
if (wxGetApp().is_closing())
return;
using NotificationLevel = NotificationManager::NotificationLevel;
enum ErrorType{
PLATER_WARNING,

View File

@@ -760,6 +760,9 @@ void Selection::clear()
#endif
// #et_FIXME fake KillFocus from sidebar
// Skip on shutdown: Plater's pImpl is already freed, so plater()->canvas3D() would use-after-free.
if (wxGetApp().is_closing())
return;
wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false);
}