diff options
Diffstat (limited to 'intern')
-rw-r--r-- | intern/clog/CLG_log.h | 1 | ||||
-rw-r--r-- | intern/clog/clog.c | 23 | ||||
-rw-r--r-- | intern/guardedalloc/MEM_guardedalloc.h | 5 | ||||
-rw-r--r-- | intern/guardedalloc/intern/leak_detector.cc | 19 |
4 files changed, 48 insertions, 0 deletions
diff --git a/intern/clog/CLG_log.h b/intern/clog/CLG_log.h index 35515a1d5c6..a2841c5c8b3 100644 --- a/intern/clog/CLG_log.h +++ b/intern/clog/CLG_log.h @@ -139,6 +139,7 @@ void CLG_exit(void); void CLG_output_set(void *file_handle); void CLG_output_use_basename_set(int value); void CLG_output_use_timestamp_set(int value); +void CLG_error_fn_set(void (*error_fn)(void *file_handle)); void CLG_fatal_fn_set(void (*fatal_fn)(void *file_handle)); void CLG_backtrace_fn_set(void (*fatal_fn)(void *file_handle)); diff --git a/intern/clog/clog.c b/intern/clog/clog.c index d384b9a89e6..84b850f5042 100644 --- a/intern/clog/clog.c +++ b/intern/clog/clog.c @@ -98,6 +98,7 @@ typedef struct CLogContext { } default_type; struct { + void (*error_fn)(void *file_handle); void (*fatal_fn)(void *file_handle); void (*backtrace_fn)(void *file_handle); } callbacks; @@ -352,6 +353,13 @@ static CLG_LogType *clg_ctx_type_register(CLogContext *ctx, const char *identifi return ty; } +static void clg_ctx_error_action(CLogContext *ctx) +{ + if (ctx->callbacks.error_fn != NULL) { + ctx->callbacks.error_fn(ctx->output_file); + } +} + static void clg_ctx_fatal_action(CLogContext *ctx) { if (ctx->callbacks.fatal_fn != NULL) { @@ -522,6 +530,10 @@ void CLG_logf(CLG_LogType *lg, clg_ctx_backtrace(lg->ctx); } + if (severity == CLG_SEVERITY_ERROR) { + clg_ctx_error_action(lg->ctx); + } + if (severity == CLG_SEVERITY_FATAL) { clg_ctx_fatal_action(lg->ctx); } @@ -555,6 +567,12 @@ static void CLG_ctx_output_use_timestamp_set(CLogContext *ctx, int value) } } +/** Action on error severity. */ +static void CLT_ctx_error_fn_set(CLogContext *ctx, void (*error_fn)(void *file_handle)) +{ + ctx->callbacks.error_fn = error_fn; +} + /** Action on fatal severity. */ static void CLG_ctx_fatal_fn_set(CLogContext *ctx, void (*fatal_fn)(void *file_handle)) { @@ -674,6 +692,11 @@ void CLG_output_use_timestamp_set(int value) CLG_ctx_output_use_timestamp_set(g_ctx, value); } +void CLG_error_fn_set(void (*error_fn)(void *file_handle)) +{ + CLT_ctx_error_fn_set(g_ctx, error_fn); +} + void CLG_fatal_fn_set(void (*fatal_fn)(void *file_handle)) { CLG_ctx_fatal_fn_set(g_ctx, fatal_fn); diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h index 9c62b2396f6..c05bda030ad 100644 --- a/intern/guardedalloc/MEM_guardedalloc.h +++ b/intern/guardedalloc/MEM_guardedalloc.h @@ -215,6 +215,11 @@ extern const char *(*MEM_name_ptr)(void *vmemh); * about memory leaks will be printed on exit. */ void MEM_init_memleak_detection(void); +/** 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 + * tests. */ +void MEM_enable_fail_on_memleak(void); + /* Switch allocator to slower but fully guarded mode. */ void MEM_use_guarded_allocator(void); diff --git a/intern/guardedalloc/intern/leak_detector.cc b/intern/guardedalloc/intern/leak_detector.cc index d7b6f749742..bb816e7f2d3 100644 --- a/intern/guardedalloc/intern/leak_detector.cc +++ b/intern/guardedalloc/intern/leak_detector.cc @@ -18,6 +18,8 @@ * \ingroup MEM */ +#include <cstdlib> + #include "MEM_guardedalloc.h" #include "mallocn_intern.h" @@ -28,6 +30,9 @@ char free_after_leak_detection_message[] = "error, use the 'construct on first use' idiom."; namespace { + +static bool fail_on_memleak = false; + class MemLeakPrinter { public: ~MemLeakPrinter() @@ -42,6 +47,15 @@ class MemLeakPrinter { leaked_blocks, (double)mem_in_use / 1024 / 1024); MEM_printmemlist(); + + if (fail_on_memleak) { + /* There are many other ways to change the exit code to failure here: + * - Make the destructor noexcept(false) and throw an exception. + * - Call exit(EXIT_FAILURE). + * - Call terminate(). + */ + abort(); + } } }; } // namespace @@ -59,3 +73,8 @@ void MEM_init_memleak_detection(void) */ static MemLeakPrinter printer; } + +void MEM_enable_fail_on_memleak(void) +{ + fail_on_memleak = true; +} |