Skip to content

Commit

Permalink
Fix requests not being marked done when they fail early
Browse files Browse the repository at this point in the history
They were marked done as far as Libcurl.cpp semantics went, but they weren't noticed by the Worker loop and thus weren't actually marked done with MarkDone.

Broken by 0cc179a where I quietly (i.e. no mention of this in the commit message >_>) replaced curl_multi_wait with curl_multi_poll, the former of which would return after some time even if nothing happened and the latter of which doesn't. Thus, the request manager loop kept iterating, if slowly, and masked this issue: these half-baked requests ended up being noticed in the iteration of the Worker loop that came after the one during which they were marked done.

Also fix the MotD being finalized improperly in Client.
  • Loading branch information
LBPHacker committed Jan 1, 2024
1 parent 70f6b68 commit 4a99004
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 11 deletions.
8 changes: 4 additions & 4 deletions src/client/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ void Client::Tick()
{
updateInfo = info.updateInfo;
applyUpdateInfo = true;
messageOfTheDay = info.messageOfTheDay;
SetMessageOfTheDay(info.messageOfTheDay);
}
for (auto &notification : info.notifications)
{
Expand All @@ -142,7 +142,7 @@ void Client::Tick()
{
if (!usingAltUpdateServer)
{
messageOfTheDay = ByteString::Build("Error while fetching MotD: ", ex.what()).FromUtf8();
SetMessageOfTheDay(ByteString::Build("Error while fetching MotD: ", ex.what()).FromUtf8());
}
}
versionCheckRequest.reset();
Expand All @@ -154,15 +154,15 @@ void Client::Tick()
auto info = alternateVersionCheckRequest->Finish();
updateInfo = info.updateInfo;
applyUpdateInfo = true;
messageOfTheDay = info.messageOfTheDay;
SetMessageOfTheDay(info.messageOfTheDay);
for (auto &notification : info.notifications)
{
AddServerNotification(notification);
}
}
catch (const http::RequestError &ex)
{
messageOfTheDay = ByteString::Build("Error while checking for updates: ", ex.what()).FromUtf8();
SetMessageOfTheDay(ByteString::Build("Error while checking for updates: ", ex.what()).FromUtf8());
}
alternateVersionCheckRequest.reset();
}
Expand Down
20 changes: 13 additions & 7 deletions src/client/http/requestmanager/Libcurl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,13 +296,8 @@ namespace http
{
{
std::lock_guard lk(sharedStateMx);
for (auto &requestHandle : requestHandles)
{
if (requestHandle->statusCode)
{
requestHandlesToUnregister.push_back(requestHandle);
}
}
// Register new handles first. This always succeeds even if the handle is "failed early" so that
// a single MarkDone call could be issued on all handles further down in this block.
for (auto &requestHandle : requestHandlesToRegister)
{
// Must not be present
Expand All @@ -311,6 +306,17 @@ namespace http
RegisterRequestHandle(requestHandle);
}
requestHandlesToRegister.clear();
// Then unregister done handles. As explained above, registering a new handle may also immediately mark
// it done and we won't be coming back here until Wait() returns, so this has to come second.
for (auto &requestHandle : requestHandles)
{
if (requestHandle->statusCode)
{
requestHandlesToUnregister.push_back(requestHandle);
}
}
// Actually unregister handles queued to be unregistered. They can be queued just above, or from another thread.
// Thus, it's ok for them to be in the queue multiple times, but it's not ok to try to unregister them multiple times.
for (auto &requestHandle : requestHandlesToUnregister)
{
auto eraseFrom = std::remove(requestHandles.begin(), requestHandles.end(), requestHandle);
Expand Down

0 comments on commit 4a99004

Please sign in to comment.