From 0f88640575566c53496bd83f9754dbb5e5eb992d Mon Sep 17 00:00:00 2001 From: SChernykh Date: Wed, 19 Jul 2023 13:13:00 +0200 Subject: [PATCH] CI: added sync test with memory leak detection --- .github/workflows/test-sync.yml | 39 +++++++++++++++++++++++++++++++++ CMakeLists.txt | 5 +++++ src/main.cpp | 7 +++--- src/memory_leak_debug.cpp | 14 ++++++++---- src/p2p_server.cpp | 6 ++--- src/side_chain.cpp | 3 +++ src/util.h | 6 ++++- 7 files changed, 68 insertions(+), 12 deletions(-) diff --git a/.github/workflows/test-sync.yml b/.github/workflows/test-sync.yml index d5ff798..d7082f9 100644 --- a/.github/workflows/test-sync.yml +++ b/.github/workflows/test-sync.yml @@ -287,3 +287,42 @@ jobs: path: | build/Debug/*.log build/Debug/data/ + + sync-test-windows-leaks: + + timeout-minutes: 30 + runs-on: windows-2022 + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Setup cmake + uses: lukka/get-cmake@latest + + - name: Build p2pool + run: | + mkdir build + cd build + cmake .. -G "Visual Studio 17 2022" -DDEV_TEST_SYNC=ON -DDEV_TRACK_MEMORY=ON + & "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Msbuild\\Current\\Bin\\amd64\\msbuild" /m /p:Configuration=RelWithDebInfo p2pool.vcxproj + + - name: Run p2pool + run: | + cd build/RelWithDebInfo + mkdir data + Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 1" + Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 2" + Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 3" + ./p2pool.exe --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6 + findstr /C:"Synchronization finished successfully" p2pool.log + + - name: Archive p2pool.log + uses: actions/upload-artifact@v3 + with: + name: p2pool_windows_data_leaks + path: | + build/RelWithDebInfo/*.log + build/RelWithDebInfo/data/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 2bf7222..bc13218 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,7 @@ option(DEV_WITH_MSAN "[Developer only] Compile with memory sanitizer" OFF) option(DEV_WITH_UBSAN "[Developer only] Compile with undefined behavior sanitizer" OFF) option(DEV_WITH_ASAN "[Developer only] Compile with address sanitizer" OFF) option(DEV_CLANG_TIDY "[Developer only] Compile for clang-tidy" OFF) +option(DEV_TRACK_MEMORY "[Developer only] Track memory allocations" OFF) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") @@ -56,6 +57,10 @@ if (DEV_CLANG_TIDY) add_definitions(-DDEV_CLANG_TIDY) endif() +if (DEV_TRACK_MEMORY) + add_definitions(-DDEV_TRACK_MEMORY) +endif() + include(cmake/flags.cmake) set(HEADERS diff --git a/src/main.cpp b/src/main.cpp index 3a9c421..3544bf8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -81,9 +81,6 @@ void p2pool_version() printf("P2Pool %s\n", p2pool::VERSION); } -void memory_tracking_start(); -void memory_tracking_stop(); - int main(int argc, char* argv[]) { if (argc == 1) { @@ -124,7 +121,9 @@ int main(int argc, char* argv[]) p2pool::destroy_crypto_cache(); - memory_tracking_stop(); + if (!memory_tracking_stop()) { + result = 1; + } return result; } diff --git a/src/memory_leak_debug.cpp b/src/memory_leak_debug.cpp index 44df222..4fc474c 100644 --- a/src/memory_leak_debug.cpp +++ b/src/memory_leak_debug.cpp @@ -18,11 +18,12 @@ #include "common.h" // Simple memory leak detector for Windows users, works best in RelWithDebInfo configuration. -#if defined(_WIN32) && 0 +#if defined(_WIN32) && defined(DEV_TRACK_MEMORY) #include "uv_util.h" #include #include +#include #include @@ -87,7 +88,7 @@ uint32_t num_allocations = 0; uint64_t total_allocated = 0; uint32_t cur_allocation_index = 1; -void show_top_10() +void show_top_10_allocations() { TrackedAllocation* buf = reinterpret_cast(VirtualAlloc(nullptr, sizeof(TrackedAllocation) * N, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)); if (!buf) { @@ -263,6 +264,9 @@ void* calloc_hook(size_t count, size_t size) noexcept void memory_tracking_start() { + // Trigger std::ostream initialization to avoid reporting it as leaks + std::cout << "Memory leak detection = " << 1 << std::endl; + SymInitialize(GetCurrentProcess(), NULL, TRUE); using namespace p2pool; @@ -272,7 +276,7 @@ void memory_tracking_start() track_memory = true; } -void memory_tracking_stop() +bool memory_tracking_stop() { using namespace p2pool; @@ -298,6 +302,8 @@ void memory_tracking_stop() } SymCleanup(h); + + return (total_leaks == 0); } NOINLINE void* operator new(size_t n) { return p2pool::allocate(n); } @@ -313,7 +319,7 @@ NOINLINE void operator delete[](void* p, size_t) noexcept { p2pool::free_hook(p) // cppcheck-suppress functionStatic void memory_tracking_start() {} // cppcheck-suppress functionStatic -void memory_tracking_stop() {} +bool memory_tracking_stop() { return true; } namespace p2pool { diff --git a/src/p2p_server.cpp b/src/p2p_server.cpp index 7d32c3e..cfa512d 100644 --- a/src/p2p_server.cpp +++ b/src/p2p_server.cpp @@ -1152,7 +1152,7 @@ void P2PServer::download_missing_blocks() continue; } - if (!m_missingBlockRequests.insert({ client->m_peerId, *id.u64() }).second) { + if (!m_missingBlockRequests.emplace(client->m_peerId, *id.u64()).second) { // We already asked this peer about this block // Don't try to ask another peer, leave it for another timer tick continue; @@ -2362,7 +2362,7 @@ void P2PServer::P2PClient::on_block_notify(const uint8_t* buf) return; } - if (!server->m_blockNotifyRequests.insert(*id.u64()).second || !server->m_missingBlockRequests.insert({ m_peerId, *id.u64() }).second) { + if (!server->m_blockNotifyRequests.insert(*id.u64()).second || !server->m_missingBlockRequests.emplace(m_peerId, *id.u64()).second) { LOGINFO(6, "BLOCK_REQUEST for id = " << id << " was already sent"); return; } @@ -2541,7 +2541,7 @@ void P2PServer::P2PClient::post_handle_incoming_block(const PoolBlock& block, co } } - if (!server->m_missingBlockRequests.insert({ m_peerId, *id.u64() }).second) { + if (!server->m_missingBlockRequests.emplace(m_peerId, *id.u64()).second) { continue; } diff --git a/src/side_chain.cpp b/src/side_chain.cpp index b492300..89301c4 100644 --- a/src/side_chain.cpp +++ b/src/side_chain.cpp @@ -2104,6 +2104,9 @@ void SideChain::prune_old_blocks() if (cur_time >= m_firstPruneTime + 120) { LOGINFO(0, log::LightGreen() << "[DEV] Synchronization finished successfully, stopping P2Pool now"); +#ifdef DEV_TRACK_MEMORY + show_top_10_allocations(); +#endif print_status(false); P2PServer* server = m_pool->p2p_server(); if (server) { diff --git a/src/util.h b/src/util.h index a37cb73..8a20bce 100644 --- a/src/util.h +++ b/src/util.h @@ -301,10 +301,14 @@ bool get_dns_txt_records_base(const std::string& host, Callback FORCEINLINE bool get_dns_txt_records(const std::string& host, T&& callback) { return get_dns_txt_records_base(host, Callback::Derived(std::move(callback))); } +#ifdef DEV_TRACK_MEMORY +void show_top_10_allocations(); +#endif + } // namespace p2pool void memory_tracking_start(); -void memory_tracking_stop(); +bool memory_tracking_stop(); void p2pool_usage(); void p2pool_version();