From b407b8927a6517d95ac90b97fde2af359fca4bb4 Mon Sep 17 00:00:00 2001 From: DanS Date: Wed, 14 Oct 2026 06:26:13 -0500 Subject: [PATCH] perf(miner): abort xmrig stat fetches on stop The miner's stats and pool-API fetches are blocking HTTP calls on the monitor thread with multi-second timeouts. When the miner was stopped, stop() still had to wait out an in-flight request before the monitor thread could join. - Both fetches now install a curl progress callback that aborts the transfer as soon as a stop is requested, so a request in flight ends promptly instead of running down its timeout. - An abort triggered by stop is treated as a clean cancellation, not a fetch failure, so it is not logged or counted against the failure warning. Co-Authored-By: Claude Opus 4.8 --- src/daemon/xmrig_manager.cpp | 7 +++++++ src/daemon/xmrig_manager.h | 3 +++ 2 files changed, 10 insertions(+) diff --git a/src/daemon/xmrig_manager.cpp b/src/daemon/xmrig_manager.cpp index 1235e76..f35a160 100644 --- a/src/daemon/xmrig_manager.cpp +++ b/src/daemon/xmrig_manager.cpp @@ -745,12 +745,16 @@ void XmrigManager::fetchStatsHttp() { curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 2000L); // 2s timeout — generous for loaded system curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, 1000L); // 1s connect timeout curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); // Avoid signal issues in threads + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); + curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, &XmrigManager::abortCb); + curl_easy_setopt(curl, CURLOPT_XFERINFODATA, this); CURLcode res = curl_easy_perform(curl); curl_slist_free_all(headers); curl_easy_cleanup(curl); if (res != CURLE_OK) { + if (should_stop_.load()) return; // aborted by stop(): not a failure static int s_fail_count = 0; if (++s_fail_count <= 5 || s_fail_count % 30 == 0) { DEBUG_LOGF("[WARN] XmrigManager::pollStats: curl failed (%d): %s url=%s\n", @@ -845,6 +849,9 @@ void XmrigManager::fetchPoolApiStats() { // pool.dragonx.cc sits behind Cloudflare and 403s odd User-Agents. curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0 (compatible; ObsidianDragon)"); curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, ""); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); + curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, &XmrigManager::abortCb); + curl_easy_setopt(curl, CURLOPT_XFERINFODATA, this); CURLcode res = curl_easy_perform(curl); curl_easy_cleanup(curl); diff --git a/src/daemon/xmrig_manager.h b/src/daemon/xmrig_manager.h index cc240c5..438562a 100644 --- a/src/daemon/xmrig_manager.h +++ b/src/daemon/xmrig_manager.h @@ -157,6 +157,9 @@ private: // Set last_error_ under error_mutex_ (writers run on both the main thread and the monitor thread). void setLastError(std::string e) { std::lock_guard lk(error_mutex_); last_error_ = std::move(e); } void fetchStatsHttp(); // Blocking HTTP call — runs on monitor thread only + // curl xfer-info callback: abort an in-flight stats fetch once stop() is requested. + static int abortCb(void* p, int64_t, int64_t, int64_t, int64_t) + { return static_cast(p)->should_stop_.load() ? 1 : 0; } void fetchPoolApiStats(); // Fetch pool-side stats (hashrate) from pool HTTP API std::atomic state_{State::Stopped};