]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Tweaks to make LSAN work
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Mon, 13 May 2024 13:42:18 +0000 (15:42 +0200)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Tue, 14 May 2024 08:26:30 +0000 (10:26 +0200)
.github/workflows/build-and-test-all.yml
pdns/recursordist/rec-main.cc
pdns/recursordist/rec_channel_rec.cc
pdns/recursordist/recursor-lsan.supp [new file with mode: 0644]
pdns/recursordist/recursor-tsan.supp
regression-tests.recursor-dnssec/recursortests.py

index 8877a3022215bd925afd1b34b7fb39fc61be464e..c40f94bb5dd4b2cfad547fa769eb5cf83d2a690d 100644 (file)
@@ -565,7 +565,8 @@ jobs:
       image: "${{ needs.get-runner-container-image.outputs.id }}:${{ needs.get-runner-container-image.outputs.tag }}"
       env:
         UBSAN_OPTIONS: 'print_stacktrace=1:halt_on_error=1:suppressions=${{ env.REPO_HOME }}/build-scripts/UBSan.supp'
-        ASAN_OPTIONS: detect_leaks=0
+        ASAN_OPTIONS: ""
+        LSAN_OPTIONS: "suppressions=${{ env.REPO_HOME }}/pdns/recursordist/recursor-lsan.supp"
         TSAN_OPTIONS: "halt_on_error=1:suppressions=${{ env.REPO_HOME }}/pdns/recursordist/recursor-tsan.supp"
       options: --sysctl net.ipv6.conf.all.disable_ipv6=0
     steps:
index 6cacb4e66dd859eb705800a023ee93d4ccbf3dbf..304718f00c8f9372ca782f4d75d0ae5ce302697d 100644 (file)
@@ -67,6 +67,18 @@ thread_local FrameStreamServersInfo t_frameStreamServersInfo;
 thread_local FrameStreamServersInfo t_nodFrameStreamServersInfo;
 #endif /* HAVE_FSTRM */
 
+/* g++ defines __SANITIZE_THREAD__
+   clang++ supports the nice __has_feature(thread_sanitizer),
+   let's merge them */
+#if defined(__has_feature)
+#if __has_feature(thread_sanitizer)
+#define __SANITIZE_THREAD__ 1
+#endif
+#if __has_feature(address_sanitizer)
+#define __SANITIZE_ADDRESS__ 1
+#endif
+#endif
+
 string g_programname = "pdns_recursor";
 string g_pidfname;
 RecursorControlChannel g_rcc; // only active in the handler thread
@@ -1870,6 +1882,10 @@ static int initForks(Logr::log_t log)
     signal(SIGTERM, termIntHandler);
     signal(SIGINT, termIntHandler);
   }
+#if defined(__SANITIZE_THREAD__) || (defined(__SANITIZE_ADDRESS__) && defined(HAVE_LEAK_SANITIZER_INTERFACE))
+  // If san is wanted, we dump the info ourselves
+  signal(SIGTERM, termIntHandler);
+#endif
 
   signal(SIGUSR1, usr1Handler);
   signal(SIGUSR2, usr2Handler);
index 3de3fbc6fe867e73ab6c360517267e25401581a3..1f82eb2f1c58737e16cbe026dd6af006904461d0 100644 (file)
 
 #include "settings/cxxsettings.hh"
 
+/* g++ defines __SANITIZE_THREAD__
+   clang++ supports the nice __has_feature(thread_sanitizer),
+   let's merge them */
+#if defined(__has_feature)
+#if __has_feature(thread_sanitizer)
+#define __SANITIZE_THREAD__ 1
+#endif
+#if __has_feature(address_sanitizer)
+#define __SANITIZE_ADDRESS__ 1
+#if defined(__SANITIZE_ADDRESS__) && defined(HAVE_LEAK_SANITIZER_INTERFACE)
+#include <sanitizer/lsan_interface.h>
+#endif
+#endif
+#endif
+
 std::pair<std::string, std::string> PrefixDashNumberCompare::prefixAndTrailingNum(const std::string& a)
 {
   auto i = a.length();
@@ -1592,8 +1607,18 @@ void registerAllStats()
   }
 }
 
+static auto clearLuaScript()
+{
+  vector<string> empty;
+  empty.emplace_back();
+  return doQueueReloadLuaScript(empty.begin(), empty.end());
+}
+
 void doExitGeneric(bool nicely)
 {
+#if defined(__SANITIZE_THREAD__)
+  _exit(0); // regression test check for exit 0
+#endif
   g_log << Logger::Error << "Exiting on user request" << endl;
   g_rcc.~RecursorControlChannel();
 
@@ -1605,8 +1630,15 @@ void doExitGeneric(bool nicely)
     RecursorControlChannel::stop = true;
   }
   else {
+#if defined(__SANITIZE_ADDRESS__) && defined(HAVE_LEAK_SANITIZER_INTERFACE)
+    clearLuaScript();
     pdns::coverage::dumpCoverageData();
-    _exit(1);
+    __lsan_do_leak_check();
+    _exit(0); // let the regression test distinguish between leaks and no leaks as __lsan_do_leak_check() exits 1 on leaks
+#else
+    pdns::coverage::dumpCoverageData();
+    _exit(1); // for historic reasons we exit 1
+#endif
   }
 }
 
@@ -2334,9 +2366,7 @@ RecursorControlChannel::Answer RecursorControlParser::getAnswer(int socket, cons
     return {0, doTraceRegex(begin == end ? FDWrapper(-1) : getfd(socket), begin, end)};
   }
   if (cmd == "unload-lua-script") {
-    vector<string> empty;
-    empty.emplace_back();
-    return doQueueReloadLuaScript(empty.begin(), empty.end());
+    return clearLuaScript();
   }
   if (cmd == "reload-acls") {
     return reloadACLs();
diff --git a/pdns/recursordist/recursor-lsan.supp b/pdns/recursordist/recursor-lsan.supp
new file mode 100644 (file)
index 0000000..e69de29
index ee6d9eaeea684ed8a06682f19acead9c55d3ebcf..859837022e7085bc26ec01c84b8a160bc40d194d 100644 (file)
@@ -1,3 +1,5 @@
 # We don't care about stats for now
 race:doStats
 race:g_stats
+# Just calling _exit in th TSAN case
+signal:termIntHandler
index 59762839ca025fd2c3257073a3132fb010eca51c..b61a5f9d2e4fbe1a1106cc7f2c1d79b8322c1a88 100644 (file)
@@ -759,7 +759,7 @@ distributor-threads={threads}""".format(confdir=confdir,
             return
         try:
             p.terminate()
-            for count in range(10):
+            for count in range(100): # tsan can be slow
                 x = p.poll()
                 if x is not None:
                     break