Mercurial > dovecot > core-2.2
comparison src/lib/ioloop.c @ 22512:bcc3a15c18a6
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.
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Tue, 08 Aug 2017 20:07:18 +0300 |
parents | ef07cc84cbb3 |
children | cb108f786fb4 |
comparison
equal
deleted
inserted
replaced
22511:f0694e6eda8d | 22512:bcc3a15c18a6 |
---|---|
1 /* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */ | 1 /* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */ |
2 | 2 |
3 #include "lib.h" | 3 #include "lib.h" |
4 #include "array.h" | 4 #include "array.h" |
5 #include "backtrace-string.h" | |
5 #include "llist.h" | 6 #include "llist.h" |
6 #include "time-util.h" | 7 #include "time-util.h" |
7 #include "istream-private.h" | 8 #include "istream-private.h" |
8 #include "ioloop-private.h" | 9 #include "ioloop-private.h" |
9 | 10 |
701 void io_loop_destroy(struct ioloop **_ioloop) | 702 void io_loop_destroy(struct ioloop **_ioloop) |
702 { | 703 { |
703 struct ioloop *ioloop = *_ioloop; | 704 struct ioloop *ioloop = *_ioloop; |
704 struct timeout *const *to_idx; | 705 struct timeout *const *to_idx; |
705 struct priorityq_item *item; | 706 struct priorityq_item *item; |
707 bool leaks = FALSE; | |
706 | 708 |
707 *_ioloop = NULL; | 709 *_ioloop = NULL; |
708 | 710 |
709 /* ->prev won't work unless loops are destroyed in create order */ | 711 /* ->prev won't work unless loops are destroyed in create order */ |
710 i_assert(ioloop == current_ioloop); | 712 i_assert(ioloop == current_ioloop); |
720 i_warning("I/O leak: %p (%s:%u, fd %d)", | 722 i_warning("I/O leak: %p (%s:%u, fd %d)", |
721 (void *)io->io.callback, | 723 (void *)io->io.callback, |
722 io->io.source_filename, | 724 io->io.source_filename, |
723 io->io.source_linenum, io->fd); | 725 io->io.source_linenum, io->fd); |
724 io_remove(&_io); | 726 io_remove(&_io); |
727 leaks = TRUE; | |
725 } | 728 } |
726 i_assert(ioloop->io_pending_count == 0); | 729 i_assert(ioloop->io_pending_count == 0); |
727 | 730 |
728 array_foreach(&ioloop->timeouts_new, to_idx) { | 731 array_foreach(&ioloop->timeouts_new, to_idx) { |
729 struct timeout *to = *to_idx; | 732 struct timeout *to = *to_idx; |
730 | 733 |
731 i_warning("Timeout leak: %p (%s:%u)", (void *)to->callback, | 734 i_warning("Timeout leak: %p (%s:%u)", (void *)to->callback, |
732 to->source_filename, | 735 to->source_filename, |
733 to->source_linenum); | 736 to->source_linenum); |
734 timeout_free(to); | 737 timeout_free(to); |
738 leaks = TRUE; | |
735 } | 739 } |
736 array_free(&ioloop->timeouts_new); | 740 array_free(&ioloop->timeouts_new); |
737 | 741 |
738 while ((item = priorityq_pop(ioloop->timeouts)) != NULL) { | 742 while ((item = priorityq_pop(ioloop->timeouts)) != NULL) { |
739 struct timeout *to = (struct timeout *)item; | 743 struct timeout *to = (struct timeout *)item; |
740 | 744 |
741 i_warning("Timeout leak: %p (%s:%u)", (void *)to->callback, | 745 i_warning("Timeout leak: %p (%s:%u)", (void *)to->callback, |
742 to->source_filename, | 746 to->source_filename, |
743 to->source_linenum); | 747 to->source_linenum); |
744 timeout_free(to); | 748 timeout_free(to); |
749 leaks = TRUE; | |
745 } | 750 } |
746 priorityq_deinit(&ioloop->timeouts); | 751 priorityq_deinit(&ioloop->timeouts); |
747 | 752 |
748 while (ioloop->wait_timers != NULL) { | 753 while (ioloop->wait_timers != NULL) { |
749 struct io_wait_timer *timer = ioloop->wait_timers; | 754 struct io_wait_timer *timer = ioloop->wait_timers; |
750 | 755 |
751 i_warning("IO wait timer leak: %s:%u", | 756 i_warning("IO wait timer leak: %s:%u", |
752 timer->source_filename, | 757 timer->source_filename, |
753 timer->source_linenum); | 758 timer->source_linenum); |
754 io_wait_timer_remove(&timer); | 759 io_wait_timer_remove(&timer); |
760 leaks = TRUE; | |
761 } | |
762 | |
763 if (leaks) { | |
764 const char *backtrace; | |
765 if (backtrace_get(&backtrace) == 0) | |
766 i_warning("Raw backtrace for leaks: %s", backtrace); | |
755 } | 767 } |
756 | 768 |
757 if (ioloop->handler_context != NULL) | 769 if (ioloop->handler_context != NULL) |
758 io_loop_handler_deinit(ioloop); | 770 io_loop_handler_deinit(ioloop); |
759 | 771 |