diff --git a/src/merge_mining_client_json_rpc.h b/src/merge_mining_client_json_rpc.h index 423c3fa..b3a6286 100644 --- a/src/merge_mining_client_json_rpc.h +++ b/src/merge_mining_client_json_rpc.h @@ -76,7 +76,7 @@ private: uv_close(reinterpret_cast(&client->m_shutdownAsync), nullptr); - delete GetLoopUserData(&client->m_loop, false); + DeleteLoopUserData(&client->m_loop); } void on_shutdown(); diff --git a/src/p2pool.cpp b/src/p2pool.cpp index 4cac425..d5b60f0 100644 --- a/src/p2pool.cpp +++ b/src/p2pool.cpp @@ -769,9 +769,7 @@ void p2pool::on_stop(uv_async_t* async) init_signals(pool, false); - uv_loop_t* loop = uv_default_loop_checked(); - delete GetLoopUserData(loop, false); - loop->data = nullptr; + DeleteLoopUserData(uv_default_loop_checked()); } void p2pool::submit_block() const diff --git a/src/pow_hash.h b/src/pow_hash.h index 64977d8..6f58415 100644 --- a/src/pow_hash.h +++ b/src/pow_hash.h @@ -121,7 +121,7 @@ private: RandomX_Hasher_RPC* server = reinterpret_cast(async->data); uv_close(reinterpret_cast(&server->m_shutdownAsync), nullptr); - delete GetLoopUserData(&server->m_loop, false); + DeleteLoopUserData(&server->m_loop); } }; diff --git a/src/tcp_server.cpp b/src/tcp_server.cpp index 68d7884..9d96cbd 100644 --- a/src/tcp_server.cpp +++ b/src/tcp_server.cpp @@ -879,7 +879,7 @@ void TCPServer::on_shutdown(uv_async_t* async) uv_close(reinterpret_cast(&s->m_dropConnectionsAsync), nullptr); uv_close(reinterpret_cast(&s->m_shutdownAsync), nullptr); - delete GetLoopUserData(&s->m_loop, false); + DeleteLoopUserData(&s->m_loop); s->m_numHandles = 0; uv_walk(&s->m_loop, [](uv_handle_t*, void* n) { (*reinterpret_cast(n))++; }, &s->m_numHandles); diff --git a/src/util.cpp b/src/util.cpp index 3b460a7..879a87c 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -667,14 +667,30 @@ bool is_localhost(const std::string& host) UV_LoopUserData* GetLoopUserData(uv_loop_t* loop, bool create) { - UV_LoopUserData* data = reinterpret_cast(loop->data); + static_assert(sizeof(std::atomic) <= sizeof(void*), "loop->data size mismatch"); + static_assert(alignof(std::atomic) <= alignof(void*), "loop->data alignment mismatch"); - if (!data && create) { - data = new UV_LoopUserData(loop); - loop->data = data; + std::atomic& data = reinterpret_cast&>(loop->data); + + UV_LoopUserData* result = data.load(); + + if (!result && create) { + UV_LoopUserData* new_data = new UV_LoopUserData(loop); + + if (data.compare_exchange_strong(result, new_data)) { + result = new_data; + } else { + delete new_data; + } } - return data; + return result; +} + +void DeleteLoopUserData(uv_loop_t* loop) +{ + std::atomic& data = reinterpret_cast&>(loop->data); + delete data.exchange(nullptr); } #ifdef WITH_UPNP diff --git a/src/uv_util.h b/src/uv_util.h index 4d8b198..78d04ea 100644 --- a/src/uv_util.h +++ b/src/uv_util.h @@ -94,7 +94,6 @@ struct UV_LoopUserData ~UV_LoopUserData() { - m_loop->data = nullptr; uv_mutex_destroy(&m_callbacksLock); uv_close(reinterpret_cast(m_async), [](uv_handle_t* h) { delete reinterpret_cast(h); }); for (const UV_LoopCallbackBase* cb : m_callbacks) { @@ -123,6 +122,7 @@ struct UV_LoopUserData }; UV_LoopUserData* GetLoopUserData(uv_loop_t* loop, bool create = true); +void DeleteLoopUserData(uv_loop_t* loop); template bool CallOnLoop(uv_loop_t* loop, T&& callback)