Skip to content

Commit fe4e287

Browse files
got3nksmrjimenez
authored andcommitted
Defer all startup HTTP downloads until after partfile + shared-file scan
The two startup HTTP downloads — the GitHub version check (amule.cpp:669) and the server.met auto-update (CServerList::Init calling AutoUpdate) — used to fire synchronously *before* the heavy local I/O in CamuleApp::OnInit (downloadqueue->LoadMetFiles + sharedfiles->Reload). On nodes with a large library this is up to a minute of saturated main thread. The wxWebSession worker thread that pumps libcurl's state machines competes for CPU with that main thread, libcurl's per-handle timeout / retry logic advances less, and DNS resolution can wall-clock out before it ever gets a chance to complete. Stoatwblr's startup log on #714 is the empirical confirmation: same hostname (upd.emule-security.org), same wxWebRequest backend, parallel execution — server.met fired before the 91k-shared-file scan and timed out after 48.8s; ipfilter.zip fired from a post-Reload main-thread event and downloaded in 3s. Move both kicks past sharedfiles->Reload so they fire with the main thread idle. CServerList::Init is split so the disk load + static-server load still run early (needed before ServerConnect), but the AutoServerlist HTTP kick is exposed as StartAutoUpdate() for the caller to invoke later. IPFilter's auto-update is already correctly deferred via its post-Reload main-thread event and is unchanged. The first-launch bootstrap-download block at amule.cpp:736 is already past the heavy I/O and is also unchanged. Refs #714.
1 parent 5c0a88f commit fe4e287

3 files changed

Lines changed: 52 additions & 19 deletions

File tree

src/ServerList.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,17 +71,26 @@ bool CServerList::Init()
7171
m_staticServersConfig = thePrefs::GetConfigDir() + "staticservers.dat";
7272
LoadStaticServers();
7373

74-
// Send the auto-update of server.met via HTTPThread requests
75-
current_url_index = 0;
76-
if ( thePrefs::AutoServerlist()) {
77-
AutoUpdate();
78-
}
74+
// The HTTP auto-update of server.met used to be kicked from here, but
75+
// that fires the libcurl request before the heavy local I/O (partfile
76+
// load + shared-file scan) — the wxWebSession worker thread then
77+
// competes with the saturated main thread for CPU, libcurl state
78+
// machine advances less, and the DNS resolution can time out on
79+
// slower setups. The kick now lives in CamuleApp::OnInit() after
80+
// sharedfiles->Reload() finishes. See StartAutoUpdate() / #714.
7981

8082
m_initialized = true;
8183
return bRes;
8284
}
8385

8486

87+
void CServerList::StartAutoUpdate()
88+
{
89+
current_url_index = 0;
90+
AutoUpdate();
91+
}
92+
93+
8594
bool CServerList::LoadServerMet(const CPath& path)
8695
{
8796
AddLogLineN(CFormat(_("Loading server.met file: %s")) % path);

src/ServerList.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,17 @@ class CServerList : public CObservableQueue<CServer*>
8282
void SetStaticServer(CServer* server, bool isStatic);
8383
void SetServerPrio(CServer* server, uint32 prio);
8484

85+
/**
86+
* Kick off the auto-update HTTP download of server.met.
87+
*
88+
* Split out of Init() so the caller can defer the HTTP request
89+
* until after the heavy startup I/O has finished, avoiding the
90+
* wxWebSession worker thread being starved by the main thread
91+
* (see #714). Caller is expected to gate this on the
92+
* AutoServerlist pref.
93+
*/
94+
void StartAutoUpdate();
95+
8596
private:
8697
virtual void ObserverAdded( ObserverType* );
8798
void AutoUpdate();

src/amule.cpp

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -660,20 +660,13 @@ bool CamuleApp::OnInit()
660660
AddLogLineNS(msg);
661661
}
662662

663-
// Test if there's any new version. The URL is the GitHub Releases
664-
// "latest" endpoint, which returns JSON describing the most recent
665-
// non-prerelease, non-draft Release. We parse the `tag_name` field
666-
// in CheckNewVersion() below. This replaces the legacy SourceForge
667-
// `lastversion` text file, which has been unmaintained since the
668-
// project moved to GitHub years ago.
669-
if (thePrefs::GetCheckNewVersion()) {
670-
// We use the thread base because I don't want a dialog to pop up.
671-
CHTTPDownloadThread* version_check =
672-
new CHTTPDownloadThread("https://api.github.com/repos/amule-org/amule/releases/latest",
673-
thePrefs::GetConfigDir() + "last_version_check", thePrefs::GetConfigDir() + "last_version", HTTP_VersionCheck, false, false);
674-
version_check->Create();
675-
version_check->Run();
676-
}
663+
// The GitHub version check and the server.met auto-update used to be
664+
// fired from here, before the partfile load + 91k-shared-file scan
665+
// run further down. On busy setups the wxWebSession worker thread
666+
// then competes with the saturated main thread for CPU, libcurl's
667+
// state machine advances less, and DNS resolution can time out
668+
// (#714). Both startup HTTP downloads now fire after
669+
// sharedfiles->Reload() returns below.
677670

678671
// Create main dialog, or fork to background (daemon).
679672
InitGui(m_geometryEnabled, m_geometryString);
@@ -711,6 +704,26 @@ bool CamuleApp::OnInit()
711704
downloadqueue->LoadMetFiles(thePrefs::GetTempDir());
712705
sharedfiles->Reload();
713706

707+
// Fire the deferred startup HTTP downloads now that the heavy local
708+
// I/O is done — see the comment in OnInit() further up.
709+
if (thePrefs::GetCheckNewVersion()) {
710+
// Test if there's any new version. The URL is the GitHub
711+
// Releases "latest" endpoint, which returns JSON describing the
712+
// most recent non-prerelease, non-draft Release. We parse the
713+
// `tag_name` field in CheckNewVersion() below. This replaces the
714+
// legacy SourceForge `lastversion` text file, which has been
715+
// unmaintained since the project moved to GitHub years ago.
716+
// We use the thread base because I don't want a dialog to pop up.
717+
CHTTPDownloadThread* version_check =
718+
new CHTTPDownloadThread("https://api.github.com/repos/amule-org/amule/releases/latest",
719+
thePrefs::GetConfigDir() + "last_version_check", thePrefs::GetConfigDir() + "last_version", HTTP_VersionCheck, false, false);
720+
version_check->Create();
721+
version_check->Run();
722+
}
723+
if (thePrefs::GetNetworkED2K() && thePrefs::AutoServerlist()) {
724+
serverlist->StartAutoUpdate();
725+
}
726+
714727
// Start the fs-watcher after the initial scan so directories exist
715728
// in shareddir_list before Add() runs. The watcher itself is cheap
716729
// when no events fire; gating it on the user pref keeps inotify

0 commit comments

Comments
 (0)