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/atomic_intrusive_ptr-inl.h1
-rw-r--r--library/cpp/yt/memory/ref.cpp5
-rw-r--r--library/cpp/yt/memory/ref.h3
-rw-r--r--library/cpp/yt/memory/ref_counted-inl.h4
-rw-r--r--library/cpp/yt/memory/unittests/ref_ut.cpp2
-rw-r--r--library/cpp/yt/memory/weak_ptr-inl.h22
-rw-r--r--library/cpp/yt/memory/weak_ptr.h2
7 files changed, 23 insertions, 16 deletions
diff --git a/library/cpp/yt/memory/atomic_intrusive_ptr-inl.h b/library/cpp/yt/memory/atomic_intrusive_ptr-inl.h
index d91d20f2fd6..4211806880f 100644
--- a/library/cpp/yt/memory/atomic_intrusive_ptr-inl.h
+++ b/library/cpp/yt/memory/atomic_intrusive_ptr-inl.h
@@ -3,7 +3,6 @@
// For the sake of sane code completion.
#include "atomic_intrusive_ptr.h"
#endif
-#undef ATOMIC_INTRUSIVE_PTR_INL_H_
#include <util/system/spinlock.h>
diff --git a/library/cpp/yt/memory/ref.cpp b/library/cpp/yt/memory/ref.cpp
index 8601c2ba3e1..eddae004ca6 100644
--- a/library/cpp/yt/memory/ref.cpp
+++ b/library/cpp/yt/memory/ref.cpp
@@ -380,11 +380,6 @@ TSharedRef TSharedRef::FromStringImpl(TString str, TRefCountedTypeCookie tagCook
return TSharedRef(ref, std::move(holder));
}
-TSharedRef TSharedRef::FromString(const char* str)
-{
- return FromString(std::string(str));
-}
-
TSharedRef TSharedRef::FromBlob(TBlob&& blob)
{
auto ref = TRef::FromBlob(blob);
diff --git a/library/cpp/yt/memory/ref.h b/library/cpp/yt/memory/ref.h
index 1fc451f50aa..91bce3fde6a 100644
--- a/library/cpp/yt/memory/ref.h
+++ b/library/cpp/yt/memory/ref.h
@@ -162,9 +162,6 @@ public:
//! Same as above but the memory tag is specified in #tagCookie.
static TSharedRef FromString(std::string str, TRefCountedTypeCookie tagCookie);
- //! Creates a TSharedRef from a zero-terminated C string.
- static TSharedRef FromString(const char* str);
-
//! Creates a TSharedRef for a given blob taking ownership of its content.
static TSharedRef FromBlob(TBlob&& blob);
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/unittests/ref_ut.cpp b/library/cpp/yt/memory/unittests/ref_ut.cpp
index 734fc030d29..175ca2bb00e 100644
--- a/library/cpp/yt/memory/unittests/ref_ut.cpp
+++ b/library/cpp/yt/memory/unittests/ref_ut.cpp
@@ -13,7 +13,7 @@ namespace {
TEST(TSharedRefTest, Save)
{
- const TSharedRef expected = TSharedRef::FromString("My tests data");
+ const TSharedRef expected = TSharedRef::FromString(std::string("My tests data"));
TStringStream s;
::Save(&s, expected); // only Save supported for TSharedRef. You can ::Load serialized data to vector.
}
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