[cfe-dev] TSAN shows data race in ~std::shared_ptr
Ben Pope
benpope81 at gmail.com
Mon Feb 17 18:51:46 PST 2014
Does the following code have a race or is it a false positive? If it's
a false positive, can I teach TSAN about it?
#include <memory>
#include <thread>
#include <iostream>
int main()
{
int v1 = 0;
int v2 = 0;
std::thread t1;
std::thread t2;
{
auto thingy = std::make_shared<int>(1);
t1 = std::thread([thingy, &v1] { v1 = *thingy; });
t2 = std::thread([thingy, &v2] { v2 = *thingy; });
}
t1.join();
t2.join();
std::cout << v1 << "\n" << v2 << "\n";
}
Compiled with:
clang++ -std=c++11 -stdlib=libc++ -pthread -lc++abi -fsanitize=thread
shared_ptr_thread_safety.cpp -o shared_ptr_thread_safety
clang version 3.4 (tags/RELEASE_34/final)
==================
WARNING: ThreadSanitizer: data race (pid=567)
Write of size 8 at 0x7d080000efd8 by thread T2:
#0 operator delete(void*)
/home/ben/development/llvm/trunk/llvm/projects/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:581
(shared_ptr_thread_safety+0x0000000483eb)
#1 std::__1::allocator<std::__1::__shared_ptr_emplace<int,
std::__1::allocator<int> >
>::deallocate(std::__1::__shared_ptr_emplace<int,
std::__1::allocator<int> >*, unsigned long)
/usr/include/c++/v1/memory:1632 (shared_ptr_thread_safety+0x0000000adb77)
#2 std::__1::__shared_ptr_emplace<int, std::__1::allocator<int>
>::__on_zero_shared_weak() /usr/include/c++/v1/memory:3744
(shared_ptr_thread_safety+0x0000000adb77)
#3 std::__1::shared_ptr<int>::~shared_ptr()
/usr/include/c++/v1/memory:4448 (shared_ptr_thread_safety+0x0000000a6f1f)
#4 main::$_1::~$_1()
/home/ben/development/test/shared_ptr_thread_safety.cpp:15
(shared_ptr_thread_safety+0x0000000a56d0)
#5 std::__1::__tuple_leaf<0ul, main::$_1, false>::~__tuple_leaf()
/usr/include/c++/v1/tuple:173 (shared_ptr_thread_safety+0x0000000a5fd0)
#6 std::__1::__tuple_impl<std::__1::__tuple_indices<0ul>,
main::$_1>::~__tuple_impl() /usr/include/c++/v1/tuple:385
(shared_ptr_thread_safety+0x0000000a5f83)
#7 std::__1::tuple<main::$_1>::~tuple()
/usr/include/c++/v1/tuple:488 (shared_ptr_thread_safety+0x0000000a5f30)
#8 std::__1::default_delete<std::__1::tuple<main::$_1>
>::operator()(std::__1::tuple<main::$_1>*) const
/usr/include/c++/v1/memory:2426 (shared_ptr_thread_safety+0x0000000a5e2f)
#9 std::__1::unique_ptr<std::__1::tuple<main::$_1>,
std::__1::default_delete<std::__1::tuple<main::$_1> >
>::reset(std::__1::tuple<main::$_1>*) /usr/include/c++/v1/memory:2625
(shared_ptr_thread_safety+0x0000000a5e2f)
#10 ~unique_ptr /usr/include/c++/v1/memory:2593
(shared_ptr_thread_safety+0x0000000a5e2f)
#11 void* std::__1::__thread_proxy<std::__1::tuple<main::$_1>
>(void*) /usr/include/c++/v1/thread:343
(shared_ptr_thread_safety+0x0000000a5e2f)
Previous read of size 4 at 0x7d080000efd8 by thread T1:
#0 main::$_0::operator()() const
/home/ben/development/test/shared_ptr_thread_safety.cpp:14
(shared_ptr_thread_safety+0x0000000a6c45)
#1
_ZNSt3__18__invokeIZ4mainE3$_0JEEEDTclclsr3std3__1E7forwardIT_Efp_Espclsr3std3__1E7forwardIT0_Efp0_EEEOS2_DpOS3_
/usr/include/c++/v1/__functional_base:413:12
(shared_ptr_thread_safety+0x0000000a6775)
#2 void
std::__1::__thread_execute<main::$_0>(std::__1::tuple<main::$_0>&,
std::__1::__tuple_indices<>) /usr/include/c++/v1/thread:332
(shared_ptr_thread_safety+0x0000000a6775)
#3 void* std::__1::__thread_proxy<std::__1::tuple<main::$_0>
>(void*) /usr/include/c++/v1/thread:342
(shared_ptr_thread_safety+0x0000000a6775)
Location is heap block of size 32 at 0x7d080000efc0 allocated by main
thread:
#0 operator new(unsigned long)
/home/ben/development/llvm/trunk/llvm/projects/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:549
(shared_ptr_thread_safety+0x000000047e7d)
#1 std::__1::allocator<std::__1::__shared_ptr_emplace<int,
std::__1::allocator<int> > >::allocate(unsigned long, void const*)
/usr/include/c++/v1/memory:1630 (shared_ptr_thread_safety+0x0000000abe69)
#2 std::__1::shared_ptr<int>
std::__1::shared_ptr<int>::make_shared<int>(int&&)
/usr/include/c++/v1/memory:4270 (shared_ptr_thread_safety+0x0000000abe69)
#3 int&&
std::__1::forward<int>(std::__1::remove_reference<int>::type&)
/usr/include/c++/v1/type_traits:1549
(shared_ptr_thread_safety+0x0000000a3176)
#4
_ZNSt3__111make_sharedIiJiEEENS_9enable_ifIXntsr8is_arrayIT_EE5valueENS_10shared_ptrIS2_EEE4typeEDpOT0_
/usr/include/c++/v1/memory:4630 (shared_ptr_thread_safety+0x0000000a3176)
#5 main /home/ben/development/test/shared_ptr_thread_safety.cpp:13
(shared_ptr_thread_safety+0x0000000a3176)
Thread T2 (tid=570, running) created by main thread at:
#0 pthread_create
/home/ben/development/llvm/trunk/llvm/projects/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:865
(shared_ptr_thread_safety+0x00000004b331)
#1 std::__1::thread::thread<main::$_1, , void>(main::$_1&&)
/usr/include/c++/v1/thread:354 (shared_ptr_thread_safety+0x0000000a4e77)
#2 main /home/ben/development/test/shared_ptr_thread_safety.cpp:15
(shared_ptr_thread_safety+0x0000000a3578)
Thread T1 (tid=569, finished) created by main thread at:
#0 pthread_create
/home/ben/development/llvm/trunk/llvm/projects/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:865
(shared_ptr_thread_safety+0x00000004b331)
#1 std::__1::thread::thread<main::$_0, , void>(main::$_0&&)
/usr/include/c++/v1/thread:354 (shared_ptr_thread_safety+0x0000000a3f57)
#2 main /home/ben/development/test/shared_ptr_thread_safety.cpp:14
(shared_ptr_thread_safety+0x0000000a32fc)
SUMMARY: ThreadSanitizer: data race /usr/include/c++/v1/memory:1632
std::__1::allocator<std::__1::__shared_ptr_emplace<int,
std::__1::allocator<int> >
>::deallocate(std::__1::__shared_ptr_emplace<int,
std::__1::allocator<int> >*, unsigned long)
==================
1
1
ThreadSanitizer: reported 1 warnings
I get the same result with clang version 3.5 (trunk 201540)
Thanks,
Ben
More information about the cfe-dev
mailing list