From 5c8193bf1e8e3d00a97a23bf7c27007eaac5deca Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 11 Jun 2025 15:22:43 +1000 Subject: [PATCH] Fix memory leak from builds without XR enabled Even when built without XR, the window-manager properties could be accessed & created but weren't freed. Exposed by !140098. --- source/blender/windowmanager/intern/wm.cc | 14 ++++++++++++++ source/blender/windowmanager/xr/intern/wm_xr.cc | 7 +++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/source/blender/windowmanager/intern/wm.cc b/source/blender/windowmanager/intern/wm.cc index 86ca0353496..7532f8fd4f4 100644 --- a/source/blender/windowmanager/intern/wm.cc +++ b/source/blender/windowmanager/intern/wm.cc @@ -554,6 +554,19 @@ void wm_add_default(Main *bmain, bContext *C) wm_window_make_drawable(wm, win); } +static void wm_xr_data_free(wmWindowManager *wm) +{ + /* NOTE: this also runs when built without `WITH_XR_OPENXR`. + * It's necessary to prevent leaks when XR data is created or loaded into non XR builds. + * This can occur when Python reads all properties (see the `bl_rna_paths` test). */ + + /* Note that non-runtime data in `wm->xr` is freed as part of freeing the window manager. */ + if (wm->xr.session_settings.shading.prop) { + IDP_FreeProperty(wm->xr.session_settings.shading.prop); + wm->xr.session_settings.shading.prop = nullptr; + } +} + void wm_close_and_free(bContext *C, wmWindowManager *wm) { if (wm->autosavetimer) { @@ -564,6 +577,7 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm) /* May send notifier, so do before freeing notifier queue. */ wm_xr_exit(wm); #endif + wm_xr_data_free(wm); while (wmWindow *win = static_cast(BLI_pophead(&wm->windows))) { /* Prevent draw clear to use screen. */ diff --git a/source/blender/windowmanager/xr/intern/wm_xr.cc b/source/blender/windowmanager/xr/intern/wm_xr.cc index 72c77561481..c8936682af6 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr.cc +++ b/source/blender/windowmanager/xr/intern/wm_xr.cc @@ -134,10 +134,9 @@ void wm_xr_exit(wmWindowManager *wm) if (wm->xr.runtime != nullptr) { wm_xr_runtime_data_free(&wm->xr.runtime); } - if (wm->xr.session_settings.shading.prop) { - IDP_FreeProperty(wm->xr.session_settings.shading.prop); - wm->xr.session_settings.shading.prop = nullptr; - } + + /* See #wm_xr_data_free for logic that frees window-manager XR data + * that may exist even when built without XR. */ } bool wm_xr_events_handle(wmWindowManager *wm)