]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Use a recursive mutex for the Lua lock
authorRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 3 Jul 2024 12:25:39 +0000 (14:25 +0200)
committerCharles-Henri Bruyand <charles-henri.bruyand@open-xchange.com>
Wed, 3 Jul 2024 12:29:03 +0000 (14:29 +0200)
pdns/dnsdistdist/dnsdist.cc
pdns/dnsdistdist/dnsdist.hh
pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc
pdns/lock.hh

index 6e5ca522488c1103ea0bf2673bb66a953b892e45..4fd2dc499b034c56b9495dca28fbf547bf21da41 100644 (file)
@@ -888,7 +888,7 @@ void responderThread(std::shared_ptr<DownstreamState> dss)
   }
 }
 
-LockGuarded<LuaContext> g_lua{LuaContext()};
+RecursiveLockGuarded<LuaContext> g_lua{LuaContext()};
 ComboAddress g_serverControl{"127.0.0.1:5199"};
 
 static void spoofResponseFromString(DNSQuestion& dnsQuestion, const string& spoofContent, bool raw)
index cf4da8f6f50dc76f8a71c7896dfab27c39e18152..1eef9fdcffc599177cd0dc676c02ce1392ec0bc6 100644 (file)
@@ -1099,7 +1099,7 @@ public:
 using servers_t = vector<std::shared_ptr<DownstreamState>>;
 
 void responderThread(std::shared_ptr<DownstreamState> dss);
-extern LockGuarded<LuaContext> g_lua;
+extern RecursiveLockGuarded<LuaContext> g_lua;
 extern std::string g_outputBuffer; // locking for this is ok, as locked by g_luamutex
 
 class DNSRule
index 013d0ba7c7faf7b42506e81f0459024962d55170..7d6569073cecce09762db884fbb256b17b5cc788 100644 (file)
@@ -15,7 +15,7 @@
 uint16_t g_maxOutstanding{std::numeric_limits<uint16_t>::max()};
 
 #include "ext/luawrapper/include/LuaContext.hpp"
-LockGuarded<LuaContext> g_lua{LuaContext()};
+RecursiveLockGuarded<LuaContext> g_lua{LuaContext()};
 
 bool g_snmpEnabled{false};
 bool g_snmpTrapsEnabled{false};
index 611d8ada02a7cecac3956c7488fc602a174dee19..3602a81a050b6fdbb8660b0d272024bbe461ac7c 100644 (file)
@@ -297,6 +297,111 @@ private:
   T d_value;
 };
 
+template <typename T>
+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<std::recursive_mutex> d_lock;
+  T& d_value;
+};
+
+template <typename T>
+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<std::recursive_mutex> d_lock;
+  T& d_value;
+};
+
+template <typename T>
+class RecursiveLockGuarded
+{
+public:
+  explicit RecursiveLockGuarded(const T& value) :
+    d_value(value)
+  {
+  }
+
+  explicit RecursiveLockGuarded(T&& value) :
+    d_value(std::move(value))
+  {
+  }
+
+  explicit RecursiveLockGuarded() = default;
+
+  RecursiveLockGuardedTryHolder<T> try_lock()
+  {
+    return RecursiveLockGuardedTryHolder<T>(d_value, d_mutex);
+  }
+
+  RecursiveLockGuardedHolder<T> lock()
+  {
+    return RecursiveLockGuardedHolder<T>(d_value, d_mutex);
+  }
+
+  RecursiveLockGuardedHolder<const T> read_only_lock()
+  {
+    return RecursiveLockGuardedHolder<const T>(d_value, d_mutex);
+  }
+
+private:
+  std::recursive_mutex d_mutex;
+  T d_value;
+};
+
 template <typename T>
 class SharedLockGuardedHolder
 {