Fix data race with calling run_state::network_time from a separate thread

This commit is contained in:
Tim Wojtulewicz 2025-03-19 15:02:55 -07:00
parent 458bf762f1
commit 8b9fe48f13
2 changed files with 6 additions and 5 deletions

View file

@ -23,7 +23,7 @@ void detail::ExpirationTimer::Dispatch(double t, bool is_expire) {
// in the interim. // in the interim.
if ( ! expire_running.test_and_set() ) { if ( ! expire_running.test_and_set() ) {
DBG_LOG(DBG_STORAGE, "Starting new expiration thread"); DBG_LOG(DBG_STORAGE, "Starting new expiration thread");
storage_mgr->expiration_thread = std::jthread([]() { storage_mgr->Expire(); }); storage_mgr->expiration_thread = std::jthread([t]() { storage_mgr->Expire(t); });
} }
storage_mgr->StartExpirationTimer(); storage_mgr->StartExpirationTimer();
@ -107,17 +107,16 @@ OperationResult Manager::CloseBackend(BackendPtr backend, ResultCallback* cb) {
return res; return res;
} }
void Manager::Expire() { void Manager::Expire(double t) {
// Expiration runs on a separate thread and loops over the vector of backends. The mutex // Expiration runs on a separate thread and loops over the vector of backends. The mutex
// here ensures exclusive access. // here ensures exclusive access.
std::unique_lock<std::mutex> lk(backends_mtx); std::unique_lock<std::mutex> lk(backends_mtx);
DBG_LOG(DBG_STORAGE, "Expiration running, have %zu backends to check", backends.size()); DBG_LOG(DBG_STORAGE, "Expiration running, have %zu backends to check", backends.size());
double current_network_time = run_state::network_time;
for ( auto it = backends.begin(); it != backends.end() && ! run_state::terminating; ++it ) { for ( auto it = backends.begin(); it != backends.end() && ! run_state::terminating; ++it ) {
if ( (*it)->IsOpen() ) if ( (*it)->IsOpen() )
(*it)->Expire(current_network_time); (*it)->Expire(t);
} }
expire_running.clear(); expire_running.clear();

View file

@ -77,8 +77,10 @@ public:
* Runs an expire operation on all open backends. This is called by the expiration * Runs an expire operation on all open backends. This is called by the expiration
* timer and shouldn't be called directly otherwise, since it should only happen on a * timer and shouldn't be called directly otherwise, since it should only happen on a
* separate thread. * separate thread.
*
* @param t The network time that the expiration started.
*/ */
void Expire(); void Expire(double t);
protected: protected:
friend class storage::detail::ExpirationTimer; friend class storage::detail::ExpirationTimer;