]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Stop the related responder thread when a backend is removed 9378/head
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 10 Aug 2020 13:51:18 +0000 (15:51 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 10 Aug 2020 13:51:18 +0000 (15:51 +0200)
pdns/dnsdist-lua.cc
pdns/dnsdist.cc
pdns/dnsdist.hh
pdns/dnsdistdist/dnsdist-backend.cc

index c6477f17f86d40a8cd32e2250fb96f4bb6e6fdeb..b46a04ca46a19c77091d7d5a07ede0b1feeed364 100644 (file)
@@ -558,6 +558,7 @@ static void setupLuaConfig(bool client, bool configCheck)
                         g_pools.setState(localPools);
                         states.erase(remove(states.begin(), states.end(), server), states.end());
                         g_dstates.setState(states);
+                        server->stop();
                       } );
 
   g_lua.writeFunction("truncateTC", [](bool tc) { setLuaSideEffect(); g_truncateTC=tc; });
index 9346c386e1aa24e23e8c928803872db3720860ed..ecf659952b5fd9e8606963dca9d8be08e46a3e12 100644 (file)
@@ -552,7 +552,7 @@ try {
   std::vector<int> sockets;
   sockets.reserve(dss->sockets.size());
 
-  for(;;) {
+  for(; !dss->isStopped(); ) {
     dnsheader* dh = reinterpret_cast<struct dnsheader*>(packet);
     try {
       pickBackendSocketsReadyForReceiving(dss, sockets);
@@ -561,8 +561,13 @@ try {
         char * response = packet;
         size_t responseSize = sizeof(packet);
 
-        if (got < 0 || static_cast<size_t>(got) < sizeof(dnsheader))
+        if (got == 0 && dss->isStopped()) {
+          break;
+        }
+
+        if (got < 0 || static_cast<size_t>(got) < sizeof(dnsheader)) {
           continue;
+        }
 
         uint16_t responseLen = static_cast<uint16_t>(got);
         queryId = dh->id;
index 04e280cca99bb1478854d83d45a5f59b78d30fd7..9c6dcd16c077eff94e07c1738ba6ca58f0e16fd8 100644 (file)
@@ -765,15 +765,8 @@ struct DownstreamState
 
   DownstreamState(const ComboAddress& remote_, const ComboAddress& sourceAddr_, unsigned int sourceItf, const std::string& sourceItfName, size_t numberOfSockets, bool connect);
   DownstreamState(const ComboAddress& remote_): DownstreamState(remote_, ComboAddress(), 0, std::string(), 1, true) {}
-  ~DownstreamState()
-  {
-    for (auto& fd : sockets) {
-      if (fd >= 0) {
-        close(fd);
-        fd = -1;
-      }
-    }
-  }
+  ~DownstreamState();
+
   boost::uuids::uuid id;
   std::vector<unsigned int> hashes;
   mutable ReadWriteLock d_lock;
@@ -883,6 +876,11 @@ struct DownstreamState
   void hash();
   void setId(const boost::uuids::uuid& newId);
   void setWeight(int newWeight);
+  void stop();
+  bool isStopped() const
+  {
+    return d_stopped;
+  }
 
   void updateTCPMetrics(size_t nbQueries, uint64_t durationMs)
   {
@@ -892,6 +890,7 @@ struct DownstreamState
 private:
   std::string name;
   std::string nameWithAddr;
+  bool d_stopped{false};
 };
 using servers_t =vector<std::shared_ptr<DownstreamState>>;
 
index 2f7a7dbff822b531cbfd43495f434561d75a0c64..38398e28eb11406b3128e5d2d57481d994300943 100644 (file)
@@ -98,6 +98,21 @@ bool DownstreamState::reconnect()
 
   return connected;
 }
+
+void DownstreamState::stop()
+{
+  std::unique_lock<std::mutex> tl(connectLock);
+  std::lock_guard<std::mutex> slock(socketsLock);
+  d_stopped = true;
+
+  for (auto& fd : sockets) {
+    if (fd != -1) {
+      /* shutdown() is needed to wake up recv() in the responderThread */
+      shutdown(fd, SHUT_RDWR);
+    }
+  }
+}
+
 void DownstreamState::hash()
 {
   vinfolog("Computing hashes for id=%s and weight=%d", id, weight);
@@ -152,5 +167,20 @@ DownstreamState::DownstreamState(const ComboAddress& remote_, const ComboAddress
     idStates.resize(g_maxOutstanding);
     sw.start();
   }
+}
+
+DownstreamState::~DownstreamState()
+{
+  for (auto& fd : sockets) {
+    if (fd >= 0) {
+      close(fd);
+      fd = -1;
+    }
+  }
 
+  // we need to either detach or join the thread before it
+  // is destroyed
+  if (threadStarted.test_and_set()) {
+    tid.detach();
+  }
 }