From c16a1d43163235e883c13392964b5833c9acac4e Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Wed, 3 Jul 2024 14:25:39 +0200 Subject: [PATCH] dnsdist: Use a recursive mutex for the Lua lock --- pdns/dnsdistdist/dnsdist.cc | 2 +- pdns/dnsdistdist/dnsdist.hh | 2 +- pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc | 2 +- pdns/lock.hh | 105 ++++++++++++++++++ 4 files changed, 108 insertions(+), 3 deletions(-) diff --git a/pdns/dnsdistdist/dnsdist.cc b/pdns/dnsdistdist/dnsdist.cc index 6e5ca522488c..4fd2dc499b03 100644 --- a/pdns/dnsdistdist/dnsdist.cc +++ b/pdns/dnsdistdist/dnsdist.cc @@ -888,7 +888,7 @@ void responderThread(std::shared_ptr dss) } } -LockGuarded g_lua{LuaContext()}; +RecursiveLockGuarded g_lua{LuaContext()}; ComboAddress g_serverControl{"127.0.0.1:5199"}; static void spoofResponseFromString(DNSQuestion& dnsQuestion, const string& spoofContent, bool raw) diff --git a/pdns/dnsdistdist/dnsdist.hh b/pdns/dnsdistdist/dnsdist.hh index cf4da8f6f50d..1eef9fdcffc5 100644 --- a/pdns/dnsdistdist/dnsdist.hh +++ b/pdns/dnsdistdist/dnsdist.hh @@ -1099,7 +1099,7 @@ public: using servers_t = vector>; void responderThread(std::shared_ptr dss); -extern LockGuarded g_lua; +extern RecursiveLockGuarded g_lua; extern std::string g_outputBuffer; // locking for this is ok, as locked by g_luamutex class DNSRule diff --git a/pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc b/pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc index 013d0ba7c7fa..7d6569073cec 100644 --- a/pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc +++ b/pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc @@ -15,7 +15,7 @@ uint16_t g_maxOutstanding{std::numeric_limits::max()}; #include "ext/luawrapper/include/LuaContext.hpp" -LockGuarded g_lua{LuaContext()}; +RecursiveLockGuarded g_lua{LuaContext()}; bool g_snmpEnabled{false}; bool g_snmpTrapsEnabled{false}; diff --git a/pdns/lock.hh b/pdns/lock.hh index 611d8ada02a7..3602a81a050b 100644 --- a/pdns/lock.hh +++ b/pdns/lock.hh @@ -297,6 +297,111 @@ private: T d_value; }; +template +class RecursiveLockGuardedHolder +{ +public: + explicit RecursiveLockGuardedHolder(T& value, std::recursive_mutex& mutex) : + d_lock(mutex), d_value(value) + { + } + + T& operator*() const noexcept + { + return d_value; + } + + T* operator->() const noexcept + { + return &d_value; + } + +private: + std::lock_guard d_lock; + T& d_value; +}; + +template +class RecursiveLockGuardedTryHolder +{ +public: + explicit RecursiveLockGuardedTryHolder(T& value, std::recursive_mutex& mutex) : + d_lock(mutex, std::try_to_lock), d_value(value) + { + } + + T& operator*() const + { + if (!owns_lock()) { + throw std::runtime_error("Trying to access data protected by a mutex while the lock has not been acquired"); + } + return d_value; + } + + T* operator->() const + { + if (!owns_lock()) { + throw std::runtime_error("Trying to access data protected by a mutex while the lock has not been acquired"); + } + return &d_value; + } + + operator bool() const noexcept + { + return d_lock.owns_lock(); + } + + [[nodiscard]] bool owns_lock() const noexcept + { + return d_lock.owns_lock(); + } + + void lock() + { + d_lock.lock(); + } + +private: + std::unique_lock d_lock; + T& d_value; +}; + +template +class RecursiveLockGuarded +{ +public: + explicit RecursiveLockGuarded(const T& value) : + d_value(value) + { + } + + explicit RecursiveLockGuarded(T&& value) : + d_value(std::move(value)) + { + } + + explicit RecursiveLockGuarded() = default; + + RecursiveLockGuardedTryHolder try_lock() + { + return RecursiveLockGuardedTryHolder(d_value, d_mutex); + } + + RecursiveLockGuardedHolder lock() + { + return RecursiveLockGuardedHolder(d_value, d_mutex); + } + + RecursiveLockGuardedHolder read_only_lock() + { + return RecursiveLockGuardedHolder(d_value, d_mutex); + } + +private: + std::recursive_mutex d_mutex; + T d_value; +}; + template class SharedLockGuardedHolder {