]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Avoid a data race reported by TSAN
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Fri, 22 Nov 2024 16:00:15 +0000 (17:00 +0100)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Tue, 11 Feb 2025 15:28:22 +0000 (16:28 +0100)
pdns/recursordist/rec-main.cc
pdns/recursordist/rec-main.hh
pdns/recursordist/reczones.cc
pdns/recursordist/ws-recursor.cc

index f554811583d1481f9653e68fbe018d15db9547c2..bd71181692d44e41f73e4cb41bb16603fb5731c0 100644 (file)
@@ -111,7 +111,7 @@ std::set<ComboAddress> g_proxyProtocolExceptions;
 boost::optional<ComboAddress> g_dns64Prefix{boost::none};
 DNSName g_dns64PrefixReverse;
 unsigned int g_maxChainLength;
-std::shared_ptr<SyncRes::domainmap_t> g_initialDomainMap; // new threads needs this to be setup
+LockGuarded<std::shared_ptr<SyncRes::domainmap_t>> g_initialDomainMap; // new threads needs this to be setup
 std::shared_ptr<NetmaskGroup> g_initialAllowFrom; // new thread needs to be setup with this
 std::shared_ptr<NetmaskGroup> g_initialAllowNotifyFrom; // new threads need this to be setup
 std::shared_ptr<notifyset_t> g_initialAllowNotifyFor; // new threads need this to be setup
@@ -351,6 +351,11 @@ int RecThreadInfo::runThreads(Logr::log_t log)
     info.setHandler();
     info.start(currentThreadId, "web+stat", cpusMap, log);
 
+    if (::arg().mustDo("webserver")) {
+      extern void serveRustWeb();
+      serveRustWeb();
+    }
+
     for (auto& tInfo : RecThreadInfo::infos()) {
       tInfo.thread.join();
       if (tInfo.exitCode != 0) {
@@ -2228,7 +2233,7 @@ static int serviceMain(Logr::log_t log)
   }
   g_networkTimeoutMsec = ::arg().asNum("network-timeout");
 
-  std::tie(g_initialDomainMap, g_initialAllowNotifyFor) = parseZoneConfiguration(g_yamlSettings);
+  std::tie(*g_initialDomainMap.lock(), g_initialAllowNotifyFor) = parseZoneConfiguration(g_yamlSettings);
 
   g_latencyStatSize = ::arg().asNum("latency-statistic-size");
 
@@ -2828,7 +2833,7 @@ static void recursorThread()
     auto& threadInfo = RecThreadInfo::self();
     {
       SyncRes tmp(g_now); // make sure it allocates tsstorage before we do anything, like primeHints or so..
-      SyncRes::setDomainMap(g_initialDomainMap);
+      SyncRes::setDomainMap(*g_initialDomainMap.lock());
       t_allowFrom = g_initialAllowFrom;
       t_allowNotifyFrom = g_initialAllowNotifyFrom;
       t_allowNotifyFor = g_initialAllowNotifyFor;
@@ -3320,10 +3325,6 @@ int main(int argc, char** argv)
       g_packetCache = std::make_unique<RecursorPacketCache>(g_maxPacketCacheEntries, ::arg().asNum("packetcache-shards"));
     }
 
-    if (::arg().mustDo("webserver")) {
-      extern void serveRustWeb();
-      serveRustWeb();
-    }
     ret = serviceMain(startupLog);
   }
   catch (const PDNSException& ae) {
index 1d07b75f3d51139049b86d1b947f3e23396c7d1f..4effb058f28058157c94a9933a16fcbe1f7b6b1c 100644 (file)
@@ -228,7 +228,7 @@ extern std::atomic<bool> g_statsWanted;
 extern uint32_t g_disthashseed;
 extern int g_argc;
 extern char** g_argv;
-extern std::shared_ptr<SyncRes::domainmap_t> g_initialDomainMap; // new threads needs this to be setup
+extern LockGuarded<std::shared_ptr<SyncRes::domainmap_t>> g_initialDomainMap; // new threads needs this to be setup
 extern std::shared_ptr<NetmaskGroup> g_initialAllowFrom; // new thread needs to be setup with this
 extern std::shared_ptr<NetmaskGroup> g_initialAllowNotifyFrom; // new threads need this to be setup
 extern std::shared_ptr<notifyset_t> g_initialAllowNotifyFor; // new threads need this to be setup
index f03ea750746a83b7795bfd7dc2e867f07f1424ef..f892225d4e2f0689dd17158e72b4ffaae47bf6df 100644 (file)
@@ -217,8 +217,8 @@ string reloadZoneConfiguration(bool yaml)
     for (const auto& entry : oldAndNewDomains) {
       wipeCaches(entry, true, 0xffff);
     }
-    extern std::shared_ptr<SyncRes::domainmap_t> g_initialDomainMap; // XXX
-    g_initialDomainMap = newDomainMap;
+    extern LockGuarded<std::shared_ptr<SyncRes::domainmap_t>> g_initialDomainMap; // XXX
+    *g_initialDomainMap.lock() = newDomainMap;
     return "ok\n";
   }
   catch (const std::exception& e) {
index 7a1a326198f9adb366d4145ea64937e0d016452d..1e112647efc5344d8c546ca83c83cd371e7c28fb 100644 (file)
@@ -359,13 +359,14 @@ static void apiServerZonesPOST(HttpRequest* req, HttpResponse* resp)
   Json document = req->json();
 
   DNSName zonename = apiNameToDNSName(stringFromJson(document, "name"));
-
-  const auto& iter = g_initialDomainMap->find(zonename);
-  if (iter != g_initialDomainMap->cend()) {
-    throw ApiException("Zone already exists");
+  {
+    auto map = g_initialDomainMap.lock();
+    const auto& iter = (*map)->find(zonename);
+    if (iter != (*map)->cend()) {
+      throw ApiException("Zone already exists");
+    }
+    doCreateZone(document);
   }
-
-  doCreateZone(document);
   reloadZoneConfiguration(g_yamlSettings);
   fillZone(zonename, resp);
   resp->status = 201;
@@ -374,7 +375,8 @@ static void apiServerZonesPOST(HttpRequest* req, HttpResponse* resp)
 static void apiServerZonesGET(HttpRequest* /* req */, HttpResponse* resp)
 {
   Json::array doc;
-  for (const auto& val : *g_initialDomainMap) {
+  auto lock = g_initialDomainMap.lock();
+  for (const auto& val : **lock) {
     const SyncRes::AuthDomain& zone = val.second;
     Json::array servers;
     for (const auto& server : zone.d_servers) {