summaryrefslogtreecommitdiffstats
path: root/library/cpp/yt/memory
diff options
context:
space:
mode:
Diffstat (limited to 'library/cpp/yt/memory')
-rw-r--r--library/cpp/yt/memory/ref_counted-inl.h4
-rw-r--r--library/cpp/yt/memory/weak_ptr-inl.h22
-rw-r--r--library/cpp/yt/memory/weak_ptr.h2
3 files changed, 22 insertions, 6 deletions
diff --git a/library/cpp/yt/memory/ref_counted-inl.h b/library/cpp/yt/memory/ref_counted-inl.h
index 94acfc6669b..ce3c686ee28 100644
--- a/library/cpp/yt/memory/ref_counted-inl.h
+++ b/library/cpp/yt/memory/ref_counted-inl.h
@@ -124,6 +124,10 @@ Y_FORCE_INLINE void DestroyRefCountedImpl(T* obj)
// No virtual call when T is final.
obj->~T();
+ // The ref-counter is a base subobject of *obj, so obj->~T() above poisons it
+ // under -fsanitize-memory-use-after-dtor. Unpoison before accessing it.
+ NSan::Unpoison(refCounter, sizeof(TRefCounter));
+
// Fast path. Weak refs cannot appear if there are neither strong nor weak refs.
if (refCounter->GetWeakRefCount() == 1) {
NYT::NDetail::TMemoryReleaser<T>::Do(obj, offset);
diff --git a/library/cpp/yt/memory/weak_ptr-inl.h b/library/cpp/yt/memory/weak_ptr-inl.h
index 11026dc5fc6..0e5ad795774 100644
--- a/library/cpp/yt/memory/weak_ptr-inl.h
+++ b/library/cpp/yt/memory/weak_ptr-inl.h
@@ -4,6 +4,8 @@
#include "weak_ptr.h"
#endif
+#include <util/system/sanitizers.h>
+
namespace NYT {
////////////////////////////////////////////////////////////////////////////////
@@ -16,8 +18,13 @@ template <class T>
TWeakPtr<T>::TWeakPtr(T* p) noexcept
: T_(p)
{
-#if defined(_tsan_enabled_)
+#if defined(_tsan_enabled_) || defined(_msan_enabled_)
if (T_) {
+ // p may legitimately point to an object whose destructor has already run
+ // while its ref-counter is still alive (weak count > 0). When T derives
+ // from TRefCounted virtually, the upcast below reads p's vptr, poisoned
+ // by -fsanitize-memory-use-after-dtor. Unpoison it (no-op for a live object).
+ NSan::Unpoison(T_, sizeof(void*));
RefCounter_ = GetRefCounter(T_);
}
#endif
@@ -42,7 +49,7 @@ TWeakPtr<T>::TWeakPtr(const TIntrusivePtr<U>& ptr) noexcept
template <class T>
TWeakPtr<T>::TWeakPtr(const TWeakPtr& other) noexcept
: T_(other.T_)
-#if defined(_tsan_enabled_)
+#if defined(_tsan_enabled_) || defined(_msan_enabled_)
, RefCounter_(other.RefCounter_)
#endif
{
@@ -77,7 +84,7 @@ TWeakPtr<T>::TWeakPtr(TWeakPtr<U>&& other) noexcept
T_ = other.T_;
other.T_ = nullptr;
-#if defined(_tsan_enabled_)
+#if defined(_tsan_enabled_) || defined(_msan_enabled_)
RefCounter_ = other.RefCounter_;
other.RefCounter_ = nullptr;
#endif
@@ -163,7 +170,7 @@ template <class T>
void TWeakPtr<T>::Swap(TWeakPtr& other) noexcept
{
DoSwap(T_, other.T_);
-#if defined(_tsan_enabled_)
+#if defined(_tsan_enabled_) || defined(_msan_enabled_)
DoSwap(RefCounter_, other.RefCounter_);
#endif
}
@@ -208,12 +215,17 @@ void TWeakPtr<T>::ReleaseRef()
if (T_) {
// Support incomplete type.
if (GetRefCounterImpl()->WeakUnref()) {
+ // The object's destructor has fully completed at this point
+ // and has poisoned T_'s vptr word under -fsanitize-memory-use-after-dtor.
+ // The upcast inside DeallocateRefCounted still needs that word
+ // to locate the virtual base.
+ NSan::Unpoison(T_, sizeof(void*));
DeallocateRefCounted(T_);
}
}
}
-#if defined(_tsan_enabled_)
+#if defined(_tsan_enabled_) || defined(_msan_enabled_)
template <class T>
const TRefCounter* TWeakPtr<T>::GetRefCounterImpl() const
{
diff --git a/library/cpp/yt/memory/weak_ptr.h b/library/cpp/yt/memory/weak_ptr.h
index d3598f62c74..c98abe15194 100644
--- a/library/cpp/yt/memory/weak_ptr.h
+++ b/library/cpp/yt/memory/weak_ptr.h
@@ -101,7 +101,7 @@ private:
friend class TWeakPtr;
T* T_ = nullptr;
-#if defined(_tsan_enabled_)
+#if defined(_tsan_enabled_) || defined(_msan_enabled_)
const TRefCounter* RefCounter_ = nullptr;
#endif