diff --git a/dbms/programs/server/Server.cpp b/dbms/programs/server/Server.cpp index ae1d995d363..77465daad27 100644 --- a/dbms/programs/server/Server.cpp +++ b/dbms/programs/server/Server.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -938,6 +939,8 @@ int Server::main(const std::vector & /*args*/) /// (they are effectively dangling objects, but they use global thread pool /// and global thread pool destructor will wait for threads, preventing server shutdown). + /// Dump coverage here, because std::atexit callback would not be called. + dumpCoverageReportIfPossible(); LOG_INFO(log, "Will shutdown forcefully."); _exit(Application::EXIT_OK); } diff --git a/docker/test/stateless_with_coverage/run.sh b/docker/test/stateless_with_coverage/run.sh index bd702737274..6d586d1d77f 100755 --- a/docker/test/stateless_with_coverage/run.sh +++ b/docker/test/stateless_with_coverage/run.sh @@ -1,15 +1,16 @@ #!/bin/bash kill_clickhouse () { + echo "clickhouse pids" `ps aux | grep clickhouse` | ts '%Y-%m-%d %H:%M:%S' kill `pgrep -u clickhouse` 2>/dev/null for i in {1..10} do if ! kill -0 `pgrep -u clickhouse`; then - echo "No clickhouse process" + echo "No clickhouse process" | ts '%Y-%m-%d %H:%M:%S' break else - echo "Process" `pgrep -u clickhouse` "still alive" + echo "Process" `pgrep -u clickhouse` "still alive" | ts '%Y-%m-%d %H:%M:%S' sleep 10 fi done @@ -18,7 +19,7 @@ kill_clickhouse () { wait_llvm_profdata () { while kill -0 `pgrep llvm-profdata-9`; do - echo "Waiting for profdata" `pgrep llvm-profdata-9` "still alive" + echo "Waiting for profdata" `pgrep llvm-profdata-9` "still alive" | ts '%Y-%m-%d %H:%M:%S' sleep 3 done } diff --git a/libs/libcommon/CMakeLists.txt b/libs/libcommon/CMakeLists.txt index 3e58cba0164..a5be37026b1 100644 --- a/libs/libcommon/CMakeLists.txt +++ b/libs/libcommon/CMakeLists.txt @@ -25,6 +25,7 @@ add_library (common src/argsToConfig.cpp src/Pipe.cpp src/phdr_cache.cpp + src/coverage.cpp include/common/SimpleCache.h include/common/Types.h @@ -51,6 +52,7 @@ add_library (common include/common/sleep.h include/common/SimpleCache.h include/common/phdr_cache.h + include/common/coverage.h include/ext/bit_cast.h include/ext/chrono_io.h diff --git a/libs/libcommon/include/common/coverage.h b/libs/libcommon/include/common/coverage.h new file mode 100644 index 00000000000..4a57528b0ce --- /dev/null +++ b/libs/libcommon/include/common/coverage.h @@ -0,0 +1,9 @@ +#pragma once + +/// Flush coverage report to file, depending on coverage system +/// proposed by compiler (llvm for clang and gcov for gcc). +/// +/// Noop if build without coverage (WITH_COVERAGE=0). +/// Thread safe (use exclusive lock). +/// Idempotent, may be called multiple times. +void dumpCoverageReportIfPossible(); diff --git a/libs/libcommon/src/coverage.cpp b/libs/libcommon/src/coverage.cpp new file mode 100644 index 00000000000..d8d3b71edd1 --- /dev/null +++ b/libs/libcommon/src/coverage.cpp @@ -0,0 +1,31 @@ +#include +#include + +#if WITH_COVERAGE + +#include +#include + +#if defined(__clang__) +extern "C" void __llvm_profile_dump(); +#elif defined(__GNUC__) || defined(__GNUG__) +extern "C" void __gcov_exit(); +#endif + +#endif + + +void dumpCoverageReportIfPossible() +{ +#if WITH_COVERAGE + static std::mutex mutex; + std::lock_guard lock(mutex); + +#if defined(__clang__) + __llvm_profile_dump(); +#elif defined(__GNUC__) || defined(__GNUG__) + __gcov_exit(); +#endif + +#endif +} diff --git a/libs/libdaemon/src/BaseDaemon.cpp b/libs/libdaemon/src/BaseDaemon.cpp index 15b61c9b454..99dfb88f2dd 100644 --- a/libs/libdaemon/src/BaseDaemon.cpp +++ b/libs/libdaemon/src/BaseDaemon.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -461,6 +462,7 @@ void BaseDaemon::terminate() void BaseDaemon::kill() { + dumpCoverageReportIfPossible(); pid.clear(); if (::raise(SIGKILL) != 0) throw Poco::SystemException("cannot kill process");