<div dir="ltr">Hi Ben, <div><br></div><div>Thanks for the test case! <br></div><div>You've hit this entry of our FAQ: </div><div><a href="https://code.google.com/p/thread-sanitizer/wiki/CppManual#FAQ">https://code.google.com/p/thread-sanitizer/wiki/CppManual#FAQ</a><br>
</div><div>==================</div><div><ul style="padding-left:25px;max-width:62em;color:rgb(0,0,0);font-family:arial,sans-serif;font-size:13px"><li style="margin-bottom:0.3em">Q: I see what looks like a false report inside the libstdc++ (libc++) code.</li>
</ul><p style="line-height:1.25em;max-width:64em;color:rgb(0,0,0);font-family:arial,sans-serif;font-size:13px">This may happen in c++11 mode. We are not aware of any such case today, but ThreadSanitizer is not heavily tested on code that uses c++11 threading. A likely solution would be to rebuild libstdc++ (libc++) with ThreadSanitizer (this might be tricky, and the process changes periodically; contact us for details). It is also possible that libstdc++ (libc++) has a bug, we've seen at least <a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59215" rel="nofollow" style="color:rgb(0,0,204)">one such</a> before.</p>
<p style="line-height:1.25em;max-width:64em;color:rgb(0,0,0);font-family:arial,sans-serif;font-size:13px"><span style="color:rgb(34,34,34);font-family:arial;font-size:small;line-height:normal">==================</span><br>
</p>Apparently, we now know about one more such case and we'll need to update the FAQ. :) <br>Good news is that this is very easy to fix: just rebuild libc++ with tsan<br>by changing the flags in projects/libcxx/lib/buildit. </div>
<div>I've just verified that using instrumented libc++ eliminates the tsan reports. </div><div><br></div><div>If curious, this is happening because shared_ptr<int>::~shared_ptr has atomic synchronization in it<br>
</div><div>and if tsan does not observe that synchronization it can not properly reason about races. </div><div><br></div><div>hth, </div><div><br></div><div>--kcc <br><p style="line-height:1.25em;max-width:64em;color:rgb(0,0,0);font-family:arial,sans-serif;font-size:13px">
<span style="color:rgb(34,34,34);font-family:arial;font-size:small;line-height:normal"><br></span></p><p style="line-height:1.25em;max-width:64em;color:rgb(0,0,0);font-family:arial,sans-serif;font-size:13px"><span style="color:rgb(34,34,34);font-family:arial;font-size:small;line-height:normal"><br>
</span></p><p style="line-height:1.25em;max-width:64em;color:rgb(0,0,0);font-family:arial,sans-serif;font-size:13px"><br></p><p style="line-height:1.25em;max-width:64em;color:rgb(0,0,0);font-family:arial,sans-serif;font-size:13px">
<br></p></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, Feb 17, 2014 at 6:51 PM, Ben Pope <span dir="ltr"><<a href="mailto:benpope81@gmail.com" target="_blank">benpope81@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">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?<br>

<br>
#include <memory><br>
#include <thread><br>
#include <iostream><br>
<br>
int main()<br>
{<br>
   int v1 = 0;<br>
   int v2 = 0;<br>
   std::thread t1;<br>
   std::thread t2;<br>
<br>
   {<br>
      auto thingy = std::make_shared<int>(1);<br>
      t1 = std::thread([thingy, &v1] { v1 = *thingy; });<br>
      t2 = std::thread([thingy, &v2] { v2 = *thingy; });<br>
   }<br>
<br>
   t1.join();<br>
   t2.join();<br>
   std::cout << v1 << "\n" << v2 << "\n";<br>
}<br>
<br>
Compiled with:<br>
clang++ -std=c++11 -stdlib=libc++ -pthread -lc++abi -fsanitize=thread shared_ptr_thread_safety.cpp -o shared_ptr_thread_safety<br>
<br>
clang version 3.4 (tags/RELEASE_34/final)<br>
<br>
==================<br>
WARNING: ThreadSanitizer: data race (pid=567)<br>
  Write of size 8 at 0x7d080000efd8 by thread T2:<br>
    #0 operator delete(void*) /home/ben/development/llvm/<u></u>trunk/llvm/projects/compiler-<u></u>rt/lib/tsan/rtl/tsan_<u></u>interceptors.cc:581 (shared_ptr_thread_safety+<u></u>0x0000000483eb)<br>
    #1 std::__1::allocator<std::__1::<u></u>__shared_ptr_emplace<int, std::__1::allocator<int> > >::deallocate(std::__1::__<u></u>shared_ptr_emplace<int, std::__1::allocator<int> >*, unsigned long) /usr/include/c++/v1/memory:<u></u>1632 (shared_ptr_thread_safety+<u></u>0x0000000adb77)<br>

    #2 std::__1::__shared_ptr_<u></u>emplace<int, std::__1::allocator<int> >::__on_zero_shared_weak() /usr/include/c++/v1/memory:<u></u>3744 (shared_ptr_thread_safety+<u></u>0x0000000adb77)<br>
    #3 std::__1::shared_ptr<int>::~<u></u>shared_ptr() /usr/include/c++/v1/memory:<u></u>4448 (shared_ptr_thread_safety+<u></u>0x0000000a6f1f)<br>
    #4 main::$_1::~$_1() /home/ben/development/test/<u></u>shared_ptr_thread_safety.cpp:<u></u>15 (shared_ptr_thread_safety+<u></u>0x0000000a56d0)<br>
    #5 std::__1::__tuple_leaf<0ul, main::$_1, false>::~__tuple_leaf() /usr/include/c++/v1/tuple:173 (shared_ptr_thread_safety+<u></u>0x0000000a5fd0)<br>
    #6 std::__1::__tuple_impl<std::__<u></u>1::__tuple_indices<0ul>, main::$_1>::~__tuple_impl() /usr/include/c++/v1/tuple:385 (shared_ptr_thread_safety+<u></u>0x0000000a5f83)<br>
    #7 std::__1::tuple<main::$_1>::~<u></u>tuple() /usr/include/c++/v1/tuple:488 (shared_ptr_thread_safety+<u></u>0x0000000a5f30)<br>
    #8 std::__1::default_delete<std::<u></u>__1::tuple<main::$_1> >::operator()(std::__1::tuple<<u></u>main::$_1>*) const /usr/include/c++/v1/memory:<u></u>2426 (shared_ptr_thread_safety+<u></u>0x0000000a5e2f)<br>

    #9 std::__1::unique_ptr<std::__1:<u></u>:tuple<main::$_1>, std::__1::default_delete<std::<u></u>__1::tuple<main::$_1> > >::reset(std::__1::tuple<main:<u></u>:$_1>*) /usr/include/c++/v1/memory:<u></u>2625 (shared_ptr_thread_safety+<u></u>0x0000000a5e2f)<br>

    #10 ~unique_ptr /usr/include/c++/v1/memory:<u></u>2593 (shared_ptr_thread_safety+<u></u>0x0000000a5e2f)<br>
    #11 void* std::__1::__thread_proxy<std::<u></u>__1::tuple<main::$_1> >(void*) /usr/include/c++/v1/thread:343 (shared_ptr_thread_safety+<u></u>0x0000000a5e2f)<br>
<br>
  Previous read of size 4 at 0x7d080000efd8 by thread T1:<br>
    #0 main::$_0::operator()() const /home/ben/development/test/<u></u>shared_ptr_thread_safety.cpp:<u></u>14 (shared_ptr_thread_safety+<u></u>0x0000000a6c45)<br>
    #1 _ZNSt3__18__invokeIZ4mainE3$_<u></u>0JEEEDTclclsr3std3__<u></u>1E7forwardIT_Efp_Espclsr3std3_<u></u>_1E7forwardIT0_Efp0_EEEOS2_<u></u>DpOS3_ /usr/include/c++/v1/__<u></u>functional_base:413:12 (shared_ptr_thread_safety+<u></u>0x0000000a6775)<br>

    #2 void std::__1::__thread_execute<<u></u>main::$_0>(std::__1::tuple<<u></u>main::$_0>&, std::__1::__tuple_indices<>) /usr/include/c++/v1/thread:332 (shared_ptr_thread_safety+<u></u>0x0000000a6775)<br>

    #3 void* std::__1::__thread_proxy<std::<u></u>__1::tuple<main::$_0> >(void*) /usr/include/c++/v1/thread:342 (shared_ptr_thread_safety+<u></u>0x0000000a6775)<br>
<br>
  Location is heap block of size 32 at 0x7d080000efc0 allocated by main thread:<br>
    #0 operator new(unsigned long) /home/ben/development/llvm/<u></u>trunk/llvm/projects/compiler-<u></u>rt/lib/tsan/rtl/tsan_<u></u>interceptors.cc:549 (shared_ptr_thread_safety+<u></u>0x000000047e7d)<br>
    #1 std::__1::allocator<std::__1::<u></u>__shared_ptr_emplace<int, std::__1::allocator<int> > >::allocate(unsigned long, void const*) /usr/include/c++/v1/memory:<u></u>1630 (shared_ptr_thread_safety+<u></u>0x0000000abe69)<br>

    #2 std::__1::shared_ptr<int> std::__1::shared_ptr<int>::<u></u>make_shared<int>(int&&) /usr/include/c++/v1/memory:<u></u>4270 (shared_ptr_thread_safety+<u></u>0x0000000abe69)<br>
    #3 int&& std::__1::forward<int>(std::__<u></u>1::remove_reference<int>::<u></u>type&) /usr/include/c++/v1/type_<u></u>traits:1549 (shared_ptr_thread_safety+<u></u>0x0000000a3176)<br>
    #4 _ZNSt3__111make_<u></u>sharedIiJiEEENS_9enable_<u></u>ifIXntsr8is_arrayIT_<u></u>EE5valueENS_10shared_ptrIS2_<u></u>EEE4typeEDpOT0_ /usr/include/c++/v1/memory:<u></u>4630 (shared_ptr_thread_safety+<u></u>0x0000000a3176)<br>

    #5 main /home/ben/development/test/<u></u>shared_ptr_thread_safety.cpp:<u></u>13 (shared_ptr_thread_safety+<u></u>0x0000000a3176)<br>
<br>
  Thread T2 (tid=570, running) created by main thread at:<br>
    #0 pthread_create /home/ben/development/llvm/<u></u>trunk/llvm/projects/compiler-<u></u>rt/lib/tsan/rtl/tsan_<u></u>interceptors.cc:865 (shared_ptr_thread_safety+<u></u>0x00000004b331)<br>
    #1 std::__1::thread::thread<main:<u></u>:$_1, , void>(main::$_1&&) /usr/include/c++/v1/thread:354 (shared_ptr_thread_safety+<u></u>0x0000000a4e77)<br>
    #2 main /home/ben/development/test/<u></u>shared_ptr_thread_safety.cpp:<u></u>15 (shared_ptr_thread_safety+<u></u>0x0000000a3578)<br>
<br>
  Thread T1 (tid=569, finished) created by main thread at:<br>
    #0 pthread_create /home/ben/development/llvm/<u></u>trunk/llvm/projects/compiler-<u></u>rt/lib/tsan/rtl/tsan_<u></u>interceptors.cc:865 (shared_ptr_thread_safety+<u></u>0x00000004b331)<br>
    #1 std::__1::thread::thread<main:<u></u>:$_0, , void>(main::$_0&&) /usr/include/c++/v1/thread:354 (shared_ptr_thread_safety+<u></u>0x0000000a3f57)<br>
    #2 main /home/ben/development/test/<u></u>shared_ptr_thread_safety.cpp:<u></u>14 (shared_ptr_thread_safety+<u></u>0x0000000a32fc)<br>
<br>
SUMMARY: ThreadSanitizer: data race /usr/include/c++/v1/memory:<u></u>1632 std::__1::allocator<std::__1::<u></u>__shared_ptr_emplace<int, std::__1::allocator<int> > >::deallocate(std::__1::__<u></u>shared_ptr_emplace<int, std::__1::allocator<int> >*, unsigned long)<br>

==================<br>
1<br>
1<br>
ThreadSanitizer: reported 1 warnings<br>
<br>
<br>
I get the same result with clang version 3.5 (trunk 201540)<br>
<br>
Thanks,<br>
<br>
Ben<br>
<br>
______________________________<u></u>_________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@cs.uiuc.edu" target="_blank">cfe-dev@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" target="_blank">http://lists.cs.uiuc.edu/<u></u>mailman/listinfo/cfe-dev</a><br>
</blockquote></div><br></div>