fix(lite): probe servers without joining the thread on the UI thread
Adding a lite server from the network tab restarted the background server probe immediately. Starting a probe while one is still running joins the previous worker thread, and that join happened on the UI thread, so the frame could stall until the outstanding probe finished. - Adding a server now sets a dirty flag instead of restarting the probe inline; the next frame starts a fresh probe once the current pass has finished, so the UI thread never blocks on a join. - The probe's libcurl transfers honor the cancel flag through a progress callback and abort cleanly, so a probe in flight stops promptly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -37,6 +37,7 @@ namespace {
|
|||||||
|
|
||||||
util::LiteServerProbe s_probe;
|
util::LiteServerProbe s_probe;
|
||||||
bool s_probeStarted = false;
|
bool s_probeStarted = false;
|
||||||
|
bool s_probeDirty = false;
|
||||||
bool s_showHidden = false;
|
bool s_showHidden = false;
|
||||||
char s_addUrl[256] = "";
|
char s_addUrl[256] = "";
|
||||||
char s_addLabel[128] = "";
|
char s_addLabel[128] = "";
|
||||||
@@ -66,6 +67,7 @@ void RenderLiteNetworkTab(App* app)
|
|||||||
const float dp = Layout::dpiScale();
|
const float dp = Layout::dpiScale();
|
||||||
|
|
||||||
if (!s_probeStarted) { startProbe(st); s_probeStarted = true; }
|
if (!s_probeStarted) { startProbe(st); s_probeStarted = true; }
|
||||||
|
if (s_probeDirty && !s_probe.busy()) { startProbe(st); s_probeDirty = false; }
|
||||||
const auto probe = s_probe.results();
|
const auto probe = s_probe.results();
|
||||||
|
|
||||||
const bool randomMode = st->getLiteServerSelectionMode() == LiteMode::Random;
|
const bool randomMode = st->getLiteServerSelectionMode() == LiteMode::Random;
|
||||||
@@ -221,7 +223,7 @@ void RenderLiteNetworkTab(App* app)
|
|||||||
servers.push_back(p);
|
servers.push_back(p);
|
||||||
st->setLiteServers(servers);
|
st->setLiteServers(servers);
|
||||||
st->save();
|
st->save();
|
||||||
startProbe(st);
|
s_probeDirty = true; // re-probe after the current pass ends (don't join the UI thread here)
|
||||||
s_addUrl[0] = '\0'; s_addLabel[0] = '\0'; s_addError.clear();
|
s_addUrl[0] = '\0'; s_addLabel[0] = '\0'; s_addError.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,17 @@
|
|||||||
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace dragonx {
|
namespace dragonx {
|
||||||
namespace util {
|
namespace util {
|
||||||
|
|
||||||
|
static int liteProbeXferCb(void* p, curl_off_t, curl_off_t, curl_off_t, curl_off_t)
|
||||||
|
{
|
||||||
|
return static_cast<const std::atomic<bool>*>(p)->load(std::memory_order_relaxed) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
std::string liteServerHost(const std::string& url)
|
std::string liteServerHost(const std::string& url)
|
||||||
{
|
{
|
||||||
// Strip scheme ("scheme://") then take everything up to the first '/', '?' or '#'.
|
// Strip scheme ("scheme://") then take everything up to the first '/', '?' or '#'.
|
||||||
@@ -69,7 +75,12 @@ void LiteServerProbe::run(std::vector<std::string> urls)
|
|||||||
curl_easy_setopt(c, CURLOPT_SSL_VERIFYPEER, 1L);
|
curl_easy_setopt(c, CURLOPT_SSL_VERIFYPEER, 1L);
|
||||||
curl_easy_setopt(c, CURLOPT_SSL_VERIFYHOST, 2L);
|
curl_easy_setopt(c, CURLOPT_SSL_VERIFYHOST, 2L);
|
||||||
|
|
||||||
|
curl_easy_setopt(c, CURLOPT_NOPROGRESS, 0L);
|
||||||
|
curl_easy_setopt(c, CURLOPT_XFERINFOFUNCTION, liteProbeXferCb);
|
||||||
|
curl_easy_setopt(c, CURLOPT_XFERINFODATA, const_cast<std::atomic<bool>*>(&cancel_));
|
||||||
|
|
||||||
const CURLcode res = curl_easy_perform(c);
|
const CURLcode res = curl_easy_perform(c);
|
||||||
|
if (res == CURLE_ABORTED_BY_CALLBACK) { curl_easy_cleanup(c); break; }
|
||||||
if (res == CURLE_OK) {
|
if (res == CURLE_OK) {
|
||||||
r.online = true;
|
r.online = true;
|
||||||
double t = 0.0;
|
double t = 0.0;
|
||||||
|
|||||||
Reference in New Issue
Block a user