[Bf-blender-cvs] [4cb4556fa5b] master: Fix T48027: Memory leaks when exiting Blender from menu

Julian Eisel noreply at git.blender.org
Thu Mar 22 23:36:34 CET 2018


Commit: 4cb4556fa5ba78fff69cf2f6cb1d156d1705a5c5
Author: Julian Eisel
Date:   Thu Mar 22 23:09:19 2018 +0100
Branches: master
https://developer.blender.org/rB4cb4556fa5ba78fff69cf2f6cb1d156d1705a5c5

Fix T48027: Memory leaks when exiting Blender from menu

You only had to close Blender through File -> Quit.

Leaks happened because WM_exit() was called from within operator, UI wasn't able
to free some of it's heap data then. This data was the handler added in
uiTemplateRunningJobs() and the IDProperty group added in uiItemFullO_ptr_ex().
There was obviously a general design issue which only became visible in this
specific case.

We now delay the WM_exit call by wrapping it into a handler that gets registered
as usual. I didn't see a better way to do this, all tricks done in
ui_apply_but_funcs_after() to prevent leaks didn't work here. In fact they may
be redundant now, but am not brave enough to try ;)

===================================================================

M	source/blender/windowmanager/intern/wm_init_exit.c
M	source/blender/windowmanager/intern/wm_operators.c
M	source/blender/windowmanager/wm.h

===================================================================

diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 7608b015f49..4fcbff6bf98 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -434,6 +434,30 @@ static void wait_for_console_key(void)
 }
 #endif
 
+static int wm_exit_handler(bContext *C, const wmEvent *event, void *userdata)
+{
+	WM_exit(C);
+
+	UNUSED_VARS(event, userdata);
+	return WM_UI_HANDLER_BREAK;
+}
+
+/**
+ * Cause a delayed WM_exit() call to avoid leaking memory when trying to exit from within operators.
+ */
+void wm_exit_schedule_delayed(const bContext *C)
+{
+	/* What we do here is a little bit hacky, but quite simple and doesn't require bigger
+	 * changes: Add a handler wrapping WM_exit() to cause a delayed call of it. */
+
+	wmWindowManager *wm = CTX_wm_manager(C);
+	/* Doesn't matter which window we use. */
+	wmWindow *win = wm->windows.first;
+
+	/* Use modal UI handler for now. Could add separate WM handlers or so, but probably not worth it. */
+	WM_event_add_ui_handler(C, &win->modalhandlers, wm_exit_handler, NULL, NULL, 0);
+}
+
 /**
  * \note doesn't run exit() call #WM_exit() for that.
  */
@@ -604,6 +628,10 @@ void WM_exit_ext(bContext *C, const bool do_python)
 	BKE_tempdir_session_purge();
 }
 
+/**
+ * \brief Main exit function to close Blender ordinarily.
+ * \note Use #wm_exit_schedule_delayed() to close Blender from an operator. Might leak memory otherwise.
+ */
 void WM_exit(bContext *C)
 {
 	WM_exit_ext(C, 1);
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 363b8e61763..bf2f00e9460 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -2160,7 +2160,7 @@ static void WM_OT_window_fullscreen_toggle(wmOperatorType *ot)
 	ot->poll = WM_operator_winactive;
 }
 
-static int wm_exit_blender_exec(bContext *C, wmOperator *op)
+static int wm_exit_blender_exec(bContext *C, wmOperator *UNUSED(op))
 {
 	wmWindowManager *wm = CTX_wm_manager(C);
 
@@ -2168,8 +2168,7 @@ static int wm_exit_blender_exec(bContext *C, wmOperator *op)
 		wm_confirm_quit(C);
 	}
 	else {
-		WM_operator_free(op);
-		WM_exit(C);
+		wm_exit_schedule_delayed(C);
 	}
 
 	return OPERATOR_FINISHED;
diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h
index a417a719b8d..5ced36a104f 100644
--- a/source/blender/windowmanager/wm.h
+++ b/source/blender/windowmanager/wm.h
@@ -43,6 +43,9 @@ typedef struct wmPaintCursor {
 	void (*draw)(bContext *C, int, int, void *customdata);
 } wmPaintCursor;
 
+
+void wm_exit_schedule_delayed(const bContext *C);
+
 extern void wm_close_and_free(bContext *C, wmWindowManager *);
 extern void wm_close_and_free_all(bContext *C, ListBase *);



More information about the Bf-blender-cvs mailing list