diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h index b64689f458b..0f7fce5a3e0 100644 --- a/intern/guardedalloc/MEM_guardedalloc.h +++ b/intern/guardedalloc/MEM_guardedalloc.h @@ -269,12 +269,6 @@ extern void (*MEM_name_ptr_set)(void *vmemh, const char *str) ATTR_NONNULL(); */ void MEM_init_memleak_detection(void); -/** - * Use this if we want to call #exit during argument parsing for example, - * without having to free all data. - */ -void MEM_use_memleak_detection(bool enabled); - /** * When this has been called and memory leaks have been detected, the process will have an exit * code that indicates failure. This can be used for when checking for memory leaks with automated diff --git a/intern/guardedalloc/intern/leak_detector.cc b/intern/guardedalloc/intern/leak_detector.cc index af478a2b38f..b5c5e3ca80d 100644 --- a/intern/guardedalloc/intern/leak_detector.cc +++ b/intern/guardedalloc/intern/leak_detector.cc @@ -24,15 +24,11 @@ char free_after_leak_detection_message[] = namespace { bool fail_on_memleak = false; -bool ignore_memleak = false; class MemLeakPrinter { public: ~MemLeakPrinter() { - if (ignore_memleak) { - return; - } leak_detector_has_run = true; const uint leaked_blocks = MEM_get_memory_blocks_in_use(); if (leaked_blocks == 0) { @@ -83,11 +79,6 @@ void MEM_init_memleak_detection() static MemLeakPrinter printer; } -void MEM_use_memleak_detection(bool enabled) -{ - ignore_memleak = !enabled; -} - void MEM_enable_fail_on_memleak() { fail_on_memleak = true; diff --git a/source/blender/windowmanager/intern/wm_playanim.cc b/source/blender/windowmanager/intern/wm_playanim.cc index d3c0f15cf5d..64d9e32d80a 100644 --- a/source/blender/windowmanager/intern/wm_playanim.cc +++ b/source/blender/windowmanager/intern/wm_playanim.cc @@ -47,6 +47,7 @@ #include "MOV_read.hh" #include "MOV_util.hh" +#include "BKE_blender.hh" #include "BKE_image.hh" #include "BIF_glutil.hh" @@ -2249,15 +2250,8 @@ int WM_main_playanim(int argc, const char **argv) AUD_exitOnce(); #endif - /* NOTE(@ideasman42): Not useful unless all subsystems are properly shutdown. */ - if (false) { - const int totblock = MEM_get_memory_blocks_in_use(); - if (totblock != 0) { - /* Prints many `bAKey`, `bArgument` messages which are tricky to fix. */ - printf("Error Totblock: %d\n", totblock); - MEM_printmemlist(); - } - } + /* Cleanup sub-systems started before this function was called. */ + BKE_blender_atexit(); return exit_code.value(); } diff --git a/source/creator/creator.cc b/source/creator/creator.cc index ca52a7fa35f..eb99151ba83 100644 --- a/source/creator/creator.cc +++ b/source/creator/creator.cc @@ -144,6 +144,11 @@ static void main_callback_setup() MEM_set_error_callback(callback_mem_error); } +/** Data to free when Blender exits early on. */ +struct CreatorAtExitData_EarlyExit { + bContext *C; +}; + /** Free data on early exit (if Python calls `sys.exit()` while parsing args for eg). */ struct CreatorAtExitData { #ifndef WITH_PYTHON_MODULE @@ -155,9 +160,11 @@ struct CreatorAtExitData { int argv_num; #endif -#if defined(WITH_PYTHON_MODULE) && !defined(USE_WIN32_UNICODE_ARGS) - void *_empty; /* Prevent empty struct error with MSVC. */ -#endif + /** + * When non-null, run additional exit logic. + * Cleared once early initialization is over. + */ + CreatorAtExitData_EarlyExit *early_exit = nullptr; }; static void callback_main_atexit(void *user_data) @@ -169,8 +176,6 @@ static void callback_main_atexit(void *user_data) BLI_args_destroy(app_init_data->ba); app_init_data->ba = nullptr; } -#else - UNUSED_VARS(app_init_data); /* May be unused. */ #endif #ifdef USE_WIN32_UNICODE_ARGS @@ -181,9 +186,21 @@ static void callback_main_atexit(void *user_data) free((void *)app_init_data->argv); app_init_data->argv = nullptr; } -#else - UNUSED_VARS(app_init_data); /* May be unused. */ #endif + + if (CreatorAtExitData_EarlyExit *early_exit = app_init_data->early_exit) { + CTX_free(early_exit->C); + + RE_texture_rng_exit(); + BKE_brush_system_exit(); + + BKE_blender_globals_clear(); + BKE_appdir_exit(); + + DNA_sdna_current_free(); + + CLG_exit(); + } } static void callback_clg_fatal(void *fp) @@ -288,6 +305,9 @@ int main(int argc, CreatorAtExitData app_init_data = {nullptr}; BKE_blender_atexit_register(callback_main_atexit, &app_init_data); + CreatorAtExitData_EarlyExit app_init_data_early_exit = {nullptr}; + app_init_data.early_exit = &app_init_data_early_exit; + /* Un-buffered `stdout` makes `stdout` and `stderr` better synchronized, and helps * when stepping through code in a debugger (prints are immediately * visible). However disabling buffering causes lock contention on windows @@ -366,6 +386,8 @@ int main(int argc, C = CTX_create(); + app_init_data_early_exit.C = C; + #ifdef WITH_PYTHON_MODULE # ifdef __APPLE__ environ = *_NSGetEnviron(); @@ -439,10 +461,6 @@ int main(int argc, main_args_setup(C, ba, false); - /* Begin argument parsing, ignore leaks so arguments that call #exit - * (such as `--version` & `--help`) don't report leaks. */ - MEM_use_memleak_detection(false); - /* Parse environment handling arguments. */ BLI_args_parse(ba, ARG_PASS_ENVIRONMENT, nullptr, nullptr); @@ -476,6 +494,9 @@ int main(int argc, main_signal_setup(); #endif + /* Continue with regular initialization, no need to use "early" exit. */ + app_init_data.early_exit = nullptr; + /* Must be initialized after #BKE_appdir_init to account for color-management paths. */ IMB_init(); /* Keep after #ARG_PASS_SETTINGS since debug flags are checked. */ @@ -543,9 +564,6 @@ int main(int argc, callback_main_atexit(&app_init_data); BKE_blender_atexit_unregister(callback_main_atexit, &app_init_data); - /* End argument parsing, allow memory leaks to be printed. */ - MEM_use_memleak_detection(true); - /* Paranoid, avoid accidental re-use. */ #ifndef WITH_PYTHON_MODULE ba = nullptr; diff --git a/source/creator/creator_args.cc b/source/creator/creator_args.cc index c2b30748656..86081f8b790 100644 --- a/source/creator/creator_args.cc +++ b/source/creator/creator_args.cc @@ -35,6 +35,7 @@ # endif # include "BKE_appdir.hh" +# include "BKE_blender.hh" # include "BKE_blender_cli_command.hh" # include "BKE_blender_version.h" # include "BKE_blendfile.hh" @@ -627,6 +628,10 @@ static const char arg_handle_print_version_doc[] = static int arg_handle_print_version(int /*argc*/, const char ** /*argv*/, void * /*data*/) { print_version_full(); + + /* Handles cleanup before exit. */ + BKE_blender_atexit(); + exit(EXIT_SUCCESS); BLI_assert_unreachable(); return 0; @@ -922,6 +927,9 @@ static int arg_handle_print_help(int /*argc*/, const char ** /*argv*/, void *dat print_help(ba, false); + /* Handles cleanup before exit. */ + BKE_blender_atexit(); + exit(EXIT_SUCCESS); BLI_assert_unreachable();