BKE_blender: Add own atexit functions
authorCampbell Barton <ideasman42@gmail.com>
Fri, 24 Jun 2016 00:05:18 +0000 (10:05 +1000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 24 Jun 2016 00:05:18 +0000 (10:05 +1000)
Runs before guarded-alloc leaks print.

source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/intern/blender.c
source/blender/windowmanager/intern/wm_init_exit.c

index 8ce85c8e6155641a1ec9a3f2f290acdcf928111a..d2d9c7630313955addd03116c0fec25a165ad94c 100644 (file)
@@ -50,6 +50,11 @@ void BKE_blender_userdef_refresh(void);
 void BKE_blender_callback_test_break_set(void (*func)(void));
 int  BKE_blender_test_break(void);
 
+/* Blenders' own atexit (avoids leaking) */
+void BKE_blender_atexit_register(void (*func)(void *user_data), void *user_data);
+void BKE_blender_atexit_unregister(void (*func)(void *user_data), const void *user_data);
+void BKE_blender_atexit(void);
+
 #ifdef __cplusplus
 }
 #endif
index 15492fbd20d7f3a8bfa49a57287df545b1e48db2..0805335da66344a63061218cf2977575f0c63097 100644 (file)
@@ -226,3 +226,56 @@ int BKE_blender_test_break(void)
        return (G.is_break == true);
 }
 
+
+/** \name Blender's AtExit
+ *
+ * \note Don't use MEM_mallocN so functions can be registered at any time.
+ * \{ */
+
+struct AtExitData {
+       struct AtExitData *next;
+
+       void (*func)(void *user_data);
+       void *user_data;
+} *g_atexit = NULL;
+
+void BKE_blender_atexit_register(void (*func)(void *user_data), void *user_data)
+{
+       struct AtExitData *ae = malloc(sizeof(*ae));
+       ae->next = g_atexit;
+       ae->func = func;
+       ae->user_data = user_data;
+       g_atexit = ae;
+}
+
+void BKE_blender_atexit_unregister(void (*func)(void *user_data), const void *user_data)
+{
+       struct AtExitData *ae = g_atexit;
+       struct AtExitData **ae_p = &g_atexit;
+
+       while (ae) {
+               if ((ae->func == func) && (ae->user_data == user_data)) {
+                       *ae_p = ae->next;
+                       free(ae);
+                       return;
+               }
+               ae_p = &ae;
+               ae = ae->next;
+       }
+}
+
+void BKE_blender_atexit(void)
+{
+       struct AtExitData *ae = g_atexit, *ae_next;
+       while (ae) {
+               ae_next = ae->next;
+
+               ae->func(ae->user_data);
+
+               free(ae);
+               ae = ae_next;
+       }
+       g_atexit = NULL;
+}
+
+/** \} */
index a1ca89c6a8ce12e66bece1f56f2c01ed67f0f7cb..2c9deb0532853c6a02d23e05adf9ad3ad3149cd1 100644 (file)
@@ -579,6 +579,8 @@ void WM_exit_ext(bContext *C, const bool do_python)
 
        BLI_threadapi_exit();
 
+       BKE_blender_atexit();
+
        if (MEM_get_memory_blocks_in_use() != 0) {
                size_t mem_in_use = MEM_get_memory_in_use() + MEM_get_memory_in_use();
                printf("Error: Not freed memory blocks: %u, total unfreed memory %f MB\n",