Open rustyx opened 4 days ago
If I look in cow_string.h
, std::string::_Rep::_M_dispose
is implemented as
void
_M_dispose(const _Alloc& __a) _GLIBCXX_NOEXCEPT
{
#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
if (__builtin_expect(this != &_S_empty_rep(), false))
#endif
{
// Be race-detector-friendly. For more info see bits/c++config.
_GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&this->_M_refcount);
// Decrement of _M_refcount is acq_rel, because:
// - all but last decrements need to release to synchronize with
// the last decrement that will delete the object.
// - the last decrement needs to acquire to synchronize with
// all the previous decrements.
// - last but one decrement needs to release to synchronize with
// the acquire load in _M_is_shared that will conclude that
// the object is not shared anymore.
if (__gnu_cxx::__exchange_and_add_dispatch(&this->_M_refcount,
-1) <= 0)
{
_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&this->_M_refcount);
_M_destroy(__a);
}
}
} // XXX MT
Could it be that legacy ABI breaks _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE
/_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER
functionality somehow?
It seems that enabling the legacy ABI with
_GLIBCXX_USE_CXX11_ABI=0
causes TSAN to report false positives in libstdc++/libgcc copy-on-write strings.Consider the following simple reproducer
When compiled with
c++ -g -std=c++17 -fsanitize=thread -D_GLIBCXX_USE_CXX11_ABI=0 repro.cpp
and run, produces:Tried with Clang 18.1.7, Clang 17.0.6, GCC 13.2.0 - same result.
For Clang need to compile with
-stdlib=libstdc++ --rtlib=libgcc
, the issue is not reproducible with libc++.