Skip to content

Commit 00c1dc2

Browse files
authored
Proof-of-concept work to identify & fix sources of logging loops (#753)
* Proof-of-concept work to identify & fix sources of logging loops (log messages that repeat forever). For discussion. Would never propose merging such ugly hacks. * Simpler syntax.
1 parent 5c597fb commit 00c1dc2

File tree

3 files changed

+40
-15
lines changed

3 files changed

+40
-15
lines changed

Code/client/Services/Generic/CharacterService.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,11 +682,17 @@ void CharacterService::OnBeastFormChange(const BeastFormChangeEvent& acEvent) co
682682

683683
Actor* pActor = Utils::GetByServerId<Actor>(serverId);
684684
if (!pActor)
685+
{
686+
spdlog::warn(__FUNCTION__ ": could not find actor server id {:X}", serverId);
685687
return;
688+
}
686689

687690
TESNPC* pNpc = Cast<TESNPC>(pActor->baseForm);
688691
if (!pNpc)
692+
{
693+
spdlog::warn(__FUNCTION__ ": could not find actor server id {:X}", serverId);
689694
return;
695+
}
690696

691697
pNpc->Serialize(&request.AppearanceBuffer);
692698
request.ChangeFlags = pNpc->GetChangeFlags();

Code/client/Services/Generic/MagicService.cpp

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -314,15 +314,15 @@ void MagicService::OnAddTargetEvent(const AddTargetEvent& acEvent) noexcept
314314
if (it == std::end(view))
315315
{
316316
spdlog::warn("Form id not found for magic add target, form id: {:X}", acEvent.TargetID);
317-
m_queuedEffects[acEvent.TargetID] = request;
317+
m_queuedEffects[acEvent.TargetID] = std::pair(0, request);
318318
return;
319319
}
320320

321321
std::optional<uint32_t> serverIdRes = Utils::GetServerId(*it);
322322
if (!serverIdRes.has_value())
323323
{
324324
spdlog::warn("Server id not found for magic add target, form id: {:X}", acEvent.TargetID);
325-
m_queuedEffects[acEvent.TargetID] = request;
325+
m_queuedEffects[acEvent.TargetID] = std::pair(0, request);
326326
return;
327327
}
328328

@@ -333,7 +333,7 @@ void MagicService::OnAddTargetEvent(const AddTargetEvent& acEvent) noexcept
333333
if (casterIt == std::end(view))
334334
{
335335
spdlog::warn("Form id not found for magic add target, form id: {:X}", acEvent.CasterID);
336-
m_queuedEffects[acEvent.TargetID] = request;
336+
m_queuedEffects[acEvent.TargetID] = std::pair(0, request);
337337
return;
338338
}
339339

@@ -356,7 +356,7 @@ void MagicService::OnNotifyAddTarget(const NotifyAddTarget& acMessage) noexcept
356356
if (!pActor)
357357
{
358358
spdlog::warn(__FUNCTION__ ": could not find actor server id {:X}", acMessage.TargetId);
359-
m_queuedRemoteEffects[acMessage.TargetId] = acMessage;
359+
m_queuedRemoteEffects[acMessage.TargetId] = std::pair(0, acMessage);
360360
return;
361361
}
362362

@@ -496,10 +496,19 @@ void MagicService::ApplyQueuedEffects() noexcept
496496

497497
Vector<uint32_t> markedForRemoval{};
498498

499-
for (auto [formId, request] : m_queuedEffects)
499+
for (auto [targetId, attemptsRequestPair] : m_queuedEffects)
500500
{
501+
// Target might never be found, it may be both created and destroyed while we are between polls.
502+
// Why is Map().second so stubbornly const? Doesn't work even with iterator, and it should, so this hack.
503+
if (++(m_queuedEffects[targetId].first) >= 5)
504+
{
505+
spdlog::warn(__FUNCTION__ ": cancelling queued magic effect after repeated failure to find targetId {:X}", targetId);
506+
markedForRemoval.push_back(targetId);
507+
continue;
508+
}
509+
501510
auto view = m_world.view<FormIdComponent>();
502-
const auto it = std::find_if(std::begin(view), std::end(view), [id = formId, view](auto entity) { return view.get<FormIdComponent>(entity).Id == id; });
511+
const auto it = std::find_if(std::begin(view), std::end(view), [id = targetId, view](auto entity) { return view.get<FormIdComponent>(entity).Id == id; });
503512

504513
if (it == std::end(view))
505514
continue;
@@ -510,25 +519,35 @@ void MagicService::ApplyQueuedEffects() noexcept
510519
if (!serverIdRes.has_value())
511520
continue;
512521

513-
request.TargetId = serverIdRes.value();
522+
attemptsRequestPair.second.TargetId = serverIdRes.value();
514523

515-
m_transport.Send(request);
524+
m_transport.Send(attemptsRequestPair.second);
516525

517-
markedForRemoval.push_back(formId);
526+
markedForRemoval.push_back(targetId);
518527
}
519528

520-
for (uint32_t formId : markedForRemoval)
521-
m_queuedEffects.erase(formId);
529+
for (uint32_t targetId : markedForRemoval)
530+
m_queuedEffects.erase(targetId);
522531

523532
markedForRemoval.clear();
524533

525-
for (const auto& [serverId, notify] : m_queuedRemoteEffects)
534+
for (auto [serverId, attemptsRequestPair] : m_queuedRemoteEffects)
526535
{
536+
if (++(m_queuedRemoteEffects[serverId].first) >= 5)
537+
{
538+
spdlog::warn(__FUNCTION__ ": cancelling queued magic effect after repeated failure to find Actor for serverId {:X}", serverId);
539+
markedForRemoval.push_back(serverId);
540+
continue;
541+
}
542+
527543
Actor* pActor = Utils::GetByServerId<Actor>(serverId);
528544
if (!pActor)
545+
{
546+
spdlog::warn(__FUNCTION__ ": could not find actor for server id {:X}", serverId);
529547
continue;
548+
}
530549

531-
OnNotifyAddTarget(notify);
550+
OnNotifyAddTarget(attemptsRequestPair.second);
532551

533552
markedForRemoval.push_back(serverId);
534553
}

Code/client/Services/MagicService.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ struct MagicService
101101
* @brief The queued magic effects.
102102
* @see ApplyQueuedEffects
103103
*/
104-
Map<uint32_t, AddTargetRequest> m_queuedEffects;
105-
Map<uint32_t, NotifyAddTarget> m_queuedRemoteEffects;
104+
Map<uint32_t, std::pair<int, AddTargetRequest>> m_queuedEffects;
105+
Map<uint32_t, std::pair<int, NotifyAddTarget>> m_queuedRemoteEffects;
106106

107107
bool m_revealingOtherPlayers = false;
108108

0 commit comments

Comments
 (0)