diff options
author | Ray Essick <essick@google.com> | 2020-01-09 11:51:27 -0800 |
---|---|---|
committer | Oliver Nguyen <olivernguyen@google.com> | 2020-02-03 19:05:39 +0000 |
commit | 572460c417e6e0fd9337e5ef6507335d6d40d42b (patch) | |
tree | 188cf180b036603889e0b35286c83f1917e71c56 | |
parent | 466d7164cf077377a82c2e598613373ed9cf590b (diff) | |
download | extras-572460c417e6e0fd9337e5ef6507335d6d40d42b.tar.gz |
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)
-rw-r--r-- | toolchain-extras/profile-extras.cpp | 15 |
1 files changed, 14 insertions, 1 deletions
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 |