From 572460c417e6e0fd9337e5ef6507335d6d40d42b Mon Sep 17 00:00:00 2001 From: Ray Essick Date: Thu, 9 Jan 2020 11:51:27 -0800 Subject: Dump coverage for all objects (a.out + dlopen()'d .so's) with code coverage enabled, the main object as well as each dlopen()ed shared library include their own copies of the hooks for dumping gcov data upon receiving signal GCOV_FLUSH_SIGNAL. Only the last one to register was actually dumped. Here, we chain the signal handlers together so that each one will call the previously registered handler to ensure that each object's coverage data is dumped. Bug: 139313557 Test: dump gcov data via kill -37 on module with dlopen() Change-Id: I376df2df6b65acff95ad5d135a7ba2bf0eac3695 Merged-In: I376df2df6b65acff95ad5d135a7ba2bf0eac3695 (cherry picked from commit b5d273da8824e8dd4bf9c28c50797364b0b47a05) --- toolchain-extras/profile-extras.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/toolchain-extras/profile-extras.cpp b/toolchain-extras/profile-extras.cpp index b7a9318a..7d78a0a5 100644 --- a/toolchain-extras/profile-extras.cpp +++ b/toolchain-extras/profile-extras.cpp @@ -31,8 +31,16 @@ extern "C" { void __gcov_flush(void); -static void gcov_signal_handler(__unused int signum) { +// storing SIG_ERR helps us detect (unlikely) looping. +static sighandler_t chained_gcov_signal_handler = SIG_ERR; + +static void gcov_signal_handler(int signum) { __gcov_flush(); + if (chained_gcov_signal_handler != SIG_ERR && + chained_gcov_signal_handler != SIG_IGN && + chained_gcov_signal_handler != SIG_DFL) { + (chained_gcov_signal_handler)(signum); + } } static const char kCoveragePropName[] = "debug.coverage.flush"; @@ -101,10 +109,15 @@ __attribute__((constructor)) int init_profile_extras(void) { return 0; init_profile_extras_once = 1; + // is this instance already registered? + if (chained_gcov_signal_handler != SIG_ERR) { + return -1; + } sighandler_t ret1 = signal(GCOV_FLUSH_SIGNAL, gcov_signal_handler); if (ret1 == SIG_ERR) { return -1; } + chained_gcov_signal_handler = ret1; // Do not create thread running property_watch_loop for zygote (it can get // invoked as zygote or app_process). This check is only needed for the -- cgit v1.2.3