# HG changeset patch # User Timo Sirainen # Date 1502212038 -10800 # Node ID bcc3a15c18a6b0e8d6528506f84b5e43cb93f469 # Parent f0694e6eda8d04295493aa4877e115ef279b4f02 lib: When logging I/O or timeout leak, log also raw backtrace This can be useful when trying to figure out where the io_loop_destroy() was called from. diff -r f0694e6eda8d -r bcc3a15c18a6 src/lib/ioloop.c --- a/src/lib/ioloop.c Tue May 23 14:05:02 2017 +0200 +++ b/src/lib/ioloop.c Tue Aug 08 20:07:18 2017 +0300 @@ -2,6 +2,7 @@ #include "lib.h" #include "array.h" +#include "backtrace-string.h" #include "llist.h" #include "time-util.h" #include "istream-private.h" @@ -703,6 +704,7 @@ struct ioloop *ioloop = *_ioloop; struct timeout *const *to_idx; struct priorityq_item *item; + bool leaks = FALSE; *_ioloop = NULL; @@ -722,6 +724,7 @@ io->io.source_filename, io->io.source_linenum, io->fd); io_remove(&_io); + leaks = TRUE; } i_assert(ioloop->io_pending_count == 0); @@ -732,6 +735,7 @@ to->source_filename, to->source_linenum); timeout_free(to); + leaks = TRUE; } array_free(&ioloop->timeouts_new); @@ -742,6 +746,7 @@ to->source_filename, to->source_linenum); timeout_free(to); + leaks = TRUE; } priorityq_deinit(&ioloop->timeouts); @@ -752,6 +757,13 @@ timer->source_filename, timer->source_linenum); io_wait_timer_remove(&timer); + leaks = TRUE; + } + + if (leaks) { + const char *backtrace; + if (backtrace_get(&backtrace) == 0) + i_warning("Raw backtrace for leaks: %s", backtrace); } if (ioloop->handler_context != NULL)