]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Add TSAN annotations in the channel code
authorRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 9 Dec 2022 15:58:15 +0000 (16:58 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 13 Jun 2023 07:59:39 +0000 (09:59 +0200)
So Thread Sanitizer knows that the object we are passing is no longer
used in the sender, and will now be used in the receiver (happens-before).

pdns/channel.hh

index fd82ca1970339d232f746ff8e49834699d969751..b13b3f988150b683e8231086a7c18f1ea4474167 100644 (file)
 
 #include "misc.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
+#endif
+
+#if __SANITIZE_THREAD__
+extern "C" void __tsan_acquire(void *addr);
+extern "C" void __tsan_release(void *addr);
+#endif
+
 namespace pdns
 {
 namespace channel
@@ -210,6 +224,9 @@ namespace channel
     auto ptr = object.get();
     static_assert(sizeof(ptr) <= PIPE_BUF, "Writes up to PIPE_BUF are guaranted not to interleaved and to either fully succeed or fail");
     while (true) {
+#if __SANITIZE_THREAD__
+      __tsan_release(ptr);
+#endif /* __SANITIZE_THREAD__ */
       ssize_t sent = write(d_fd.getHandle(), &ptr, sizeof(ptr));
 
       if (sent == sizeof(ptr)) {
@@ -218,6 +235,9 @@ namespace channel
         return true;
       }
       else {
+#if __SANITIZE_THREAD__
+      __tsan_acquire(ptr);
+#endif /* __SANITIZE_THREAD__ */
         if (errno == EINTR) {
           continue;
         }
@@ -251,6 +271,9 @@ namespace channel
       T* obj{nullptr};
       ssize_t got = read(d_fd.getHandle(), &obj, sizeof(obj));
       if (got == sizeof(obj)) {
+#if __SANITIZE_THREAD__
+        __tsan_acquire(obj);
+#endif /* __SANITIZE_THREAD__ */
         return std::unique_ptr<T, D>(obj, deleter);
       }
       else if (got == 0) {