From 3cb1b7fd2f4b3fd656758060582001f1e78c3e12 Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Mon, 17 Apr 2017 21:14:15 +0200 Subject: [PATCH] Call libc and libstdc++ freeres functions in heaptrack_preload on exit These functions are used by Valgrind already and can be used to force a clean shutdown of libc and libstdc++. Both usually don't bother freeing their global resources, which used to be reported as memory leaks by heaptrack. By calling the freeres functions we now get a clean shutdown of the libc_leaks.c example without any memory leaks reported. Thanks to Maxim Golov for pointing out this hidden functionality and providing a test case. BUG: 378765 --- src/track/heaptrack_preload.cpp | 19 +++++++++++++++++++ tests/manual/CMakeLists.txt | 2 ++ tests/manual/libc_leaks.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 tests/manual/libc_leaks.c diff --git a/src/track/heaptrack_preload.cpp b/src/track/heaptrack_preload.cpp index 149b194..ae18913 100644 --- a/src/track/heaptrack_preload.cpp +++ b/src/track/heaptrack_preload.cpp @@ -40,6 +40,13 @@ using namespace std; # define HAVE_CFREE 0 #endif +extern "C" { +__attribute__((weak)) void __libc_freeres(); +} +namespace __gnu_cxx { +__attribute__((weak)) extern void __freeres(); +} + namespace { namespace hooks { @@ -120,6 +127,18 @@ void* dummy_calloc(size_t num, size_t size) noexcept void init() { + atexit([]() { + // free internal libstdc++ resources + // see also Valgrind's `--run-cxx-freeres` option + if (&__gnu_cxx::__freeres) { + __gnu_cxx::__freeres(); + } + // free internal libc resources, cf: https://bugs.kde.org/show_bug.cgi?id=378765 + // see also Valgrind's `--run-libc-freeres` option + if (&__libc_freeres) { + __libc_freeres(); + } + }); heaptrack_init(getenv("DUMP_HEAPTRACK_OUTPUT"), [] { hooks::calloc.original = &dummy_calloc; diff --git a/tests/manual/CMakeLists.txt b/tests/manual/CMakeLists.txt index 62ebdd8..831c7e2 100644 --- a/tests/manual/CMakeLists.txt +++ b/tests/manual/CMakeLists.txt @@ -15,3 +15,5 @@ add_executable(test_aggregation test_aggregation.cpp) add_executable(signals signals.cpp) target_link_libraries(signals ${CMAKE_THREAD_LIBS_INIT}) + +add_executable(libc_leaks libc_leaks.c) diff --git a/tests/manual/libc_leaks.c b/tests/manual/libc_leaks.c new file mode 100644 index 0000000..748187c --- /dev/null +++ b/tests/manual/libc_leaks.c @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Maxim Golov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include + +int main(int argc, char **argv) +{ + time_t t = time(0); + struct tm tmbuf; + gmtime_r(&t, &tmbuf); + char buf[16]; + strftime(buf, sizeof(buf), "%d", &tmbuf); +} -- 2.7.4