From b5001bc2588b4a07ff41a968e4bccdcaeebbc69c Mon Sep 17 00:00:00 2001 From: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com> Date: Tue, 3 Feb 2026 18:27:00 +0000 Subject: [PATCH] fixes to static variable destruction issue. Signed-off-by: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com> --- include/xrpl/basics/LocalValue.h | 67 +++++++++++++++++++------------- include/xrpl/core/Coro.ipp | 11 ++++-- 2 files changed, 47 insertions(+), 31 deletions(-) diff --git a/include/xrpl/basics/LocalValue.h b/include/xrpl/basics/LocalValue.h index 8c664116c3..58ad586223 100644 --- a/include/xrpl/basics/LocalValue.h +++ b/include/xrpl/basics/LocalValue.h @@ -1,8 +1,6 @@ #ifndef XRPL_BASICS_LOCALVALUE_H_INCLUDED #define XRPL_BASICS_LOCALVALUE_H_INCLUDED -#include - #include #include @@ -42,21 +40,45 @@ struct LocalValues // Keys are the address of a LocalValue. std::unordered_map> values; - - static inline void - cleanup(LocalValues* lvs) - { - if (lvs && !lvs->onCoro) - delete lvs; - } }; -template -boost::thread_specific_ptr& -getLocalValues() +inline LocalValues*& +getLocalValuesPtr() { - static boost::thread_specific_ptr tsp(&detail::LocalValues::cleanup); - return tsp; + thread_local LocalValues* ptr = nullptr; + return ptr; +} + +inline LocalValues* +getOrCreateLocalValues() +{ + auto& ptr = getLocalValuesPtr(); + if (!ptr) + { + ptr = new LocalValues(); + ptr->onCoro = false; + } + return ptr; +} + +// For coroutine support, we need explicit swap functions +inline LocalValues* +releaseLocalValues() +{ + auto& ptr = getLocalValuesPtr(); + auto* result = ptr; + ptr = nullptr; + return result; +} + +inline void +resetLocalValues(LocalValues* lvs) +{ + auto& ptr = getLocalValuesPtr(); + // Clean up old value if it's not a coroutine's LocalValues + if (ptr && !ptr->onCoro) + delete ptr; + ptr = lvs; } } // namespace detail @@ -89,19 +111,10 @@ template T& LocalValue::operator*() { - auto lvs = detail::getLocalValues().get(); - if (!lvs) - { - lvs = new detail::LocalValues(); - lvs->onCoro = false; - detail::getLocalValues().reset(lvs); - } - else - { - auto const iter = lvs->values.find(this); - if (iter != lvs->values.end()) - return *reinterpret_cast(iter->second->get()); - } + auto lvs = detail::getOrCreateLocalValues(); + auto const iter = lvs->values.find(this); + if (iter != lvs->values.end()) + return *reinterpret_cast(iter->second->get()); return *reinterpret_cast( lvs->values.emplace(this, std::make_unique>(t_)).first->second->get()); diff --git a/include/xrpl/core/Coro.ipp b/include/xrpl/core/Coro.ipp index 40067a77e9..f87fda47d5 100644 --- a/include/xrpl/core/Coro.ipp +++ b/include/xrpl/core/Coro.ipp @@ -73,13 +73,16 @@ JobQueue::Coro::resume() std::lock_guard lock(jq_.m_mutex); --jq_.nSuspend_; } - auto saved = detail::getLocalValues().release(); - detail::getLocalValues().reset(&lvs_); + auto saved = detail::releaseLocalValues(); + detail::resetLocalValues(&lvs_); std::lock_guard lock(mutex_); XRPL_ASSERT(static_cast(coro_), "xrpl::JobQueue::Coro::resume : is runnable"); coro_(); - detail::getLocalValues().release(); - detail::getLocalValues().reset(saved); + + // Restore the thread's original LocalValues + detail::releaseLocalValues(); + detail::resetLocalValues(saved); + std::lock_guard lk(mutex_run_); running_ = false; cv_.notify_all();