From c6552ad381003a23cde7c3228e7071f30465df35 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Wed, 6 Apr 2022 19:41:01 +0200 Subject: [PATCH 1/2] macro: call __gcov_dump() before _exit() w/ coverage enabled _exit() skips at-exit hooks, causing lost coverage from processes utilizing it. Hopefully resolves systemd/systemd-centos-ci#482 --- meson.build | 3 +++ src/basic/macro.h | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/meson.build b/meson.build index 0455d89b78..26f98b856c 100644 --- a/meson.build +++ b/meson.build @@ -47,6 +47,9 @@ fuzzer_build = want_ossfuzz or want_libfuzzer # More items are added later after they have been detected. summary({'build mode' : get_option('mode')}) +# GCOV doesn't define any macro when compiled with, so let's define it ourselves +conf.set10('BUILT_WITH_COVERAGE', get_option('b_coverage')) + ##################################################################### # Try to install the git pre-commit hook diff --git a/src/basic/macro.h b/src/basic/macro.h index 68d8b062e8..685de73449 100644 --- a/src/basic/macro.h +++ b/src/basic/macro.h @@ -29,6 +29,19 @@ #define _alignptr_ __attribute__((__aligned__(sizeof(void*)))) #define _warn_unused_result_ __attribute__((__warn_unused_result__)) +#if defined(BUILT_WITH_COVERAGE) && BUILT_WITH_COVERAGE +/* We need to explicitly call __gcov_dump() in places where we use _exit(), since + * _exit() skips at-exit hooks resulting in lost coverage */ +# include +extern void __gcov_dump(void); + +_noreturn_ static inline void _coverage__exit(int status) { + __gcov_dump(); + _exit(status); +} +# define _exit(x) _coverage__exit(x) +#endif + #if !defined(HAS_FEATURE_MEMORY_SANITIZER) # if defined(__has_feature) # if __has_feature(memory_sanitizer) From 1b2e3b8bffce0df580a9c8228cb39b823547bf11 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Thu, 7 Apr 2022 12:45:13 +0200 Subject: [PATCH 2/2] test: ignore missing coverage in TEST-02 Since c6552ad we now try to collect coverage even in situations where it's basically impossible (like in test-mount-util where the whole / is mounted as read-only). As dealing with this is not worth the trouble, let's ignore the missing coverage errors thrown by gcov in such cases. --- test/TEST-02-UNITTESTS/test.sh | 4 ++++ test/test-functions | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/test/TEST-02-UNITTESTS/test.sh b/test/TEST-02-UNITTESTS/test.sh index 571abe41c3..80cb82a50d 100755 --- a/test/TEST-02-UNITTESTS/test.sh +++ b/test/TEST-02-UNITTESTS/test.sh @@ -4,6 +4,10 @@ set -e TEST_DESCRIPTION="Run unit tests under containers" RUN_IN_UNPRIVILEGED_CONTAINER=yes +# Some tests make collecting coverage impossible (like test-mount-util, which +# remounts the whole / as read-only), so let's ignore the gcov errors in such +# case +IGNORE_MISSING_COVERAGE=yes # embed some newlines in the kernel command line to stress our test suite KERNEL_APPEND=" diff --git a/test/test-functions b/test/test-functions index c734a15ca9..47eae9f0cb 100644 --- a/test/test-functions +++ b/test/test-functions @@ -1406,8 +1406,8 @@ check_coverage_reports() { # usually due to the sandbox being too restrictive (e.g. ProtectSystem=yes, # ProtectHome=yes) or the $BUILD_DIR being inaccessible to non-root users - see # `setfacl` stuff in install_compiled_systemd(). - - if "${JOURNALCTL:?}" -q --no-pager -D "${root:?}/var/log/journal" --grep "profiling:.+?gcda:[Cc]annot open"; then + if ! get_bool "${IGNORE_MISSING_COVERAGE:=}" && \ + "${JOURNALCTL:?}" -q --no-pager -D "${root:?}/var/log/journal" --grep "profiling:.+?gcda:[Cc]annot open"; then derror "Detected possibly missing coverage, check the journal" return 1 fi