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};