[PATCH] D21609: [tsan] Intercept libcxx __release_shared to avoid false positive with weak_ptrs and destructors in C++
Kuba Brecka via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 23 10:11:44 PDT 2016
kubabrecka updated this revision to Diff 61697.
kubabrecka added a comment.
Updating the patch to re-implement the whole method using.
http://reviews.llvm.org/D21609
Files:
lib/tsan/rtl/tsan_interceptors_mac.cc
test/tsan/Darwin/libcxx-shared-ptr.mm
Index: test/tsan/Darwin/libcxx-shared-ptr.mm
===================================================================
--- test/tsan/Darwin/libcxx-shared-ptr.mm
+++ test/tsan/Darwin/libcxx-shared-ptr.mm
@@ -0,0 +1,50 @@
+// RUN: %clang_tsan %s -o %t -framework Foundation
+// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+
+#import <Foundation/Foundation.h>
+
+#import <memory>
+
+#import "../test.h"
+
+long my_global;
+
+struct MyStruct {
+ void setGlobal() {
+ my_global = 42;
+ }
+ ~MyStruct() {
+ my_global = 43;
+ }
+};
+
+int main(int argc, const char *argv[]) {
+ fprintf(stderr, "Hello world.\n");
+ print_address("addr=", 1, &my_global);
+ barrier_init(&barrier, 2);
+
+ std::shared_ptr<MyStruct> shared(new MyStruct());
+
+ dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+
+ std::weak_ptr<MyStruct> weak(shared);
+
+ dispatch_async(q, ^{
+ {
+ std::shared_ptr<MyStruct> strong = weak.lock();
+ if (!strong) exit(1);
+
+ strong->setGlobal();
+ }
+ barrier_wait(&barrier);
+ });
+
+ barrier_wait(&barrier);
+ shared.reset();
+
+ fprintf(stderr, "Done.\n");
+}
+
+// CHECK: Hello world.
+// CHECK: Done.
+// CHECK-NOT: WARNING: ThreadSanitizer
Index: lib/tsan/rtl/tsan_interceptors_mac.cc
===================================================================
--- lib/tsan/rtl/tsan_interceptors_mac.cc
+++ lib/tsan/rtl/tsan_interceptors_mac.cc
@@ -273,6 +273,37 @@
(connection, message, replyq, new_handler);
}
+// On macOS, libc++ is always linked dynamically, so intercepting works the
+// usual way.
+#define STDCXX_INTERCEPTOR TSAN_INTERCEPTOR
+
+namespace {
+struct fake_shared_weak_count {
+ volatile a64 shared_owners;
+ volatile a64 shared_weak_owners;
+ virtual void _unused_0x0() = 0;
+ virtual void _unused_0x8() = 0;
+ virtual void on_zero_shared() = 0;
+ virtual void _unused_0x18() = 0;
+ virtual void on_zero_shared_weak() = 0;
+};
+}
+
+// This adds a libc++ interceptor for:
+// void __shared_weak_count::__release_shared() _NOEXCEPT;
+// Shared and weak pointers in C++ maintain reference counts via atomics in
+// libc++.dylib, which are TSan-invisible, and this leads to false positives in
+// destructor code. This interceptor re-implements the whole function so that
+// the mo_acq_rel semantics of the atomic decrement are visible.
+STDCXX_INTERCEPTOR(void, _ZNSt3__119__shared_weak_count16__release_sharedEv,
+ fake_shared_weak_count *o) {
+ if (__tsan_atomic64_fetch_add(&o->shared_owners, -1, mo_acq_rel) == 0) {
+ o->on_zero_shared();
+ if (__tsan_atomic64_fetch_add(&o->shared_weak_owners, -1, mo_acq_rel) == 0)
+ o->on_zero_shared_weak();
+ }
+}
+
} // namespace __tsan
#endif // SANITIZER_MAC
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D21609.61697.patch
Type: text/x-patch
Size: 2795 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160623/9da7e3cc/attachment.bin>
More information about the llvm-commits
mailing list