From a9bea85bfffb429a66bf1b4fd527a36eaae13a2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jiri=20Dan=C4=9Bk?= Date: Sun, 23 Apr 2023 11:55:54 +0200 Subject: [PATCH] Issue #1072: add `LSAN_DO_LEAK_CHECK` macro to suppress _all_ shutdown lsan leaks --- src/dispatch.c | 5 +++++ src/qd_asan_interface.h | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/dispatch.c b/src/dispatch.c index fc27056b9..0c035dd59 100644 --- a/src/dispatch.c +++ b/src/dispatch.c @@ -30,6 +30,7 @@ #include "log_private.h" #include "message_private.h" #include "policy.h" +#include "qd_asan_interface.h" #include "router_private.h" #include "qpid/dispatch/alloc.h" @@ -373,6 +374,10 @@ void qd_dispatch_free(qd_dispatch_t *qd) { if (!qd) return; + // Run a final lsan leakcheck right here (if lsan is enabled) + // only leaks (i.e. memory made unreachable) before this point will be reported by lsan + LSAN_DO_LEAK_CHECK(); + /* Stop HTTP threads immediately */ qd_http_server_free(qd_server_http(qd->server)); diff --git a/src/qd_asan_interface.h b/src/qd_asan_interface.h index a3b4e77a5..bf90ab92a 100644 --- a/src/qd_asan_interface.h +++ b/src/qd_asan_interface.h @@ -54,6 +54,8 @@ extern "C" { void __asan_poison_memory_region(void const volatile *addr, size_t size); void __asan_unpoison_memory_region(void const volatile *addr, size_t size); +void __lsan_do_leak_check(void); +int __lsan_do_recoverable_leak_check(void); /// Marks a memory region as unaddressable. /// @@ -73,6 +75,25 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size); /// \param size Size of memory region. #define ASAN_UNPOISON_MEMORY_REGION(addr, size) __asan_unpoison_memory_region((addr), (size)) +// Check for leaks now. This function behaves identically to the default +// end-of-process leak check. In particular, it will terminate the process if +// leaks are found and the exitcode runtime flag is non-zero. +// Subsequent calls to this function will have no effect and end-of-process +// leak check will not run. Effectively, end-of-process leak check is moved to +// the time of first invocation of this function. +// By calling this function early during process shutdown, you can instruct +// LSan to ignore shutdown-only leaks which happen later on. +#define LSAN_DO_LEAK_CHECK() __lsan_do_leak_check() + +// Check for leaks now. Returns zero if no leaks have been found or if leak +// detection is disabled, non-zero otherwise. +// This function may be called repeatedly, e.g. to periodically check a +// long-running process. It prints a leak report if appropriate, but does not +// terminate the process. It does not affect the behavior of +// __lsan_do_leak_check() or the end-of-process leak check, and is not +// affected by them. +#define LSAN_DO_RECOVERABLE_LEAK_CHECK() __lsan_do_recoverable_leak_check() + #ifdef __cplusplus } // extern "C" #endif @@ -84,6 +105,9 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size); #define ASAN_UNPOISON_MEMORY_REGION(addr, size) \ ((void)(addr), (void)(size)) +#define LSAN_DO_LEAK_CHECK() /**/ +#define LSAN_DO_RECOVERABLE_LEAK_CHECK() 0 + #endif // QD_HAS_ADDRESS_SANITIZER // https://github.com/google/sanitizers/wiki/AddressSanitizer#turning-off-instrumentation