]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Implement an "atExit" Lua callback to clean up leftovers
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 6 May 2024 14:36:39 +0000 (16:36 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 7 May 2024 07:13:32 +0000 (09:13 +0200)
pdns/dnsdistdist/dnsdist-lsan.supp
pdns/dnsdistdist/dnsdist-lua-network.cc
pdns/dnsdistdist/dnsdist.cc
pdns/dnsdistdist/doh.cc
regression-tests.dnsdist/test_Async.py
regression-tests.dnsdist/test_Routing.py

index a04f7122a82e8315fc703724cacd5548c172fa32..64bf7122c5a9095497801e971ed34735a32b9703 100644 (file)
@@ -1,2 +1,2 @@
-# h2o
-leak:create_socket
+# it's hard to clean up the per-thread Lua load-balancing policies on exit
+leak:setupLuaLoadBalancingContext
index 56a58cd5cf8bb29cac08b1efaf96da9b2938441b..58ad214ad5f7359e17c5ecd2d81400e9da0d16d2 100644 (file)
@@ -41,6 +41,11 @@ NetworkListener::NetworkListener() :
 NetworkListener::~NetworkListener()
 {
   d_data->d_exiting = true;
+
+  /* wake up the listening thread */
+  for (const auto& socket : d_data->d_sockets) {
+    shutdown(socket.second.getHandle(), SHUT_RD);
+  }
 }
 
 void NetworkListener::readCB(int desc, FDMultiplexer::funcparam_t& param)
index 1911e34180ff9d286d8a23aaeebf377ba5fe2c1c..954450202fe052a1767df2946205b23c325e9313 100644 (file)
@@ -2810,9 +2810,14 @@ static void sigTermHandler([[maybe_unused]] int sig)
   std::cout << "Exiting on user request" << std::endl;
 #endif /* __SANITIZE_THREAD__ */
 #if defined(__SANITIZE_ADDRESS__) && defined(HAVE_LEAK_SANITIZER_INTERFACE)
-  auto lock = g_lua.lock();
-  cleanupLuaObjects();
-  *lock = LuaContext();
+  if (dnsdist::g_asyncHolder) {
+    dnsdist::g_asyncHolder->stop();
+  }
+  {
+    auto lock = g_lua.lock();
+    cleanupLuaObjects();
+    *lock = LuaContext();
+  }
   __lsan_do_leak_check();
 #endif /* __SANITIZE_ADDRESS__ && HAVE_LEAK_SANITIZER_INTERFACE */
   _exit(EXIT_SUCCESS);
index 292e0d68cadfd3afd5f320048a2c9759a61aa22d..6bdd5764712a44608158693aa0bf52d8e23215c9 100644 (file)
@@ -212,6 +212,7 @@ struct DOHServerConfig
   std::set<std::string, std::less<>> paths;
   h2o_globalconf_t h2o_config{};
   h2o_context_t h2o_ctx{};
+  std::unique_ptr<h2o_socket_t,decltype(&h2o_socket_close)> h2o_socket{nullptr, h2o_socket_close};
   std::shared_ptr<DOHAcceptContext> accept_ctx{nullptr};
   ClientState* clientState{nullptr};
   std::shared_ptr<DOHFrontend> dohFrontend{nullptr};
@@ -1430,9 +1431,9 @@ static void on_accept(h2o_socket_t *listener, const char *err)
 
 static int create_listener(std::shared_ptr<DOHServerConfig>& dsc, int descriptor)
 {
-  auto* sock = h2o_evloop_socket_create(dsc->h2o_ctx.loop, descriptor, H2O_SOCKET_FLAG_DONT_READ);
-  sock->data = dsc.get();
-  h2o_socket_read_start(sock, on_accept);
+  dsc->h2o_socket = std::unique_ptr<h2o_socket_t, decltype(&h2o_socket_close)>{h2o_evloop_socket_create(dsc->h2o_ctx.loop, descriptor, H2O_SOCKET_FLAG_DONT_READ), &h2o_socket_close};
+  dsc->h2o_socket->data = dsc.get();
+  h2o_socket_read_start(dsc->h2o_socket.get(), on_accept);
 
   return 0;
 }
@@ -1599,11 +1600,11 @@ void dohThread(ClientState* clientState)
     dsc->h2o_ctx.storage.entries[0].data = dsc.get();
     ++dsc->h2o_ctx.storage.size;
 
-    auto* sock = h2o_evloop_socket_create(dsc->h2o_ctx.loop, dsc->d_responseReceiver.getDescriptor(), H2O_SOCKET_FLAG_DONT_READ);
+    auto sock = std::unique_ptr<h2o_socket_t, decltype(&h2o_socket_close)>{h2o_evloop_socket_create(dsc->h2o_ctx.loop, dsc->d_responseReceiver.getDescriptor(), H2O_SOCKET_FLAG_DONT_READ), &h2o_socket_close};
     sock->data = dsc.get();
 
     // this listens to responses from dnsdist to turn into http responses
-    h2o_socket_read_start(sock, on_dnsdist);
+    h2o_socket_read_start(sock.get(), on_dnsdist);
 
     setupAcceptContext(*dsc->accept_ctx, *dsc, false);
 
@@ -1628,6 +1629,7 @@ void dohThread(ClientState* clientState)
     }
     while (!stop);
 
+    h2o_evloop_destroy(dsc->h2o_ctx.loop);
   }
   catch (const std::exception& e) {
     throw runtime_error("DOH thread failed to launch: " + std::string(e.what()));
index eda4a5903c33ea1c959e2585abd0bea903bcb018..bb37c7ee12e8dbd15df90e1372a2c1d25e6862c6 100644 (file)
@@ -510,6 +510,11 @@ class TestAsyncFFI(DNSDistTest, AsyncTests):
       return DNSResponseAction.Allow
     end
 
+    function atExit()
+      listener = nil
+      collectgarbage()
+    end
+
     -- this only matters for tests actually reaching the backend
     addAction('tcp-only.async.tests.powerdns.com', PoolAction('tcp-only', false))
     addAction('cache.async.tests.powerdns.com', PoolAction('cache', false))
@@ -618,6 +623,11 @@ class TestAsyncLua(DNSDistTest, AsyncTests):
       return DNSResponseAction.Allow
     end
 
+    function atExit()
+      listener = nil
+      collectgarbage()
+    end
+
     -- this only matters for tests actually reaching the backend
     addAction('tcp-only.async.tests.powerdns.com', PoolAction('tcp-only', false))
     addAction('cache.async.tests.powerdns.com', PoolAction('cache', false))
index 186cba069217e39ff790e4c0d3ccf754ac0fba0b..1f32f98d7399e05ac338e267f65c4a64f959d5cf 100644 (file)
@@ -352,6 +352,11 @@ class TestRoutingLuaFFIPerThreadRoundRobinLB(RoundRobinTest, DNSDistTest):
     s1:setUp()
     s2 = newServer{address="127.0.0.1:%s"}
     s2:setUp()
+
+    function atExit()
+      setServerPolicy(leastOutstanding)
+      collectgarbage()
+    end
     """
 
     @classmethod