[LLVMbugs] [Bug 23293] New: libcxx: racy use-after-free on condition_variable
bugzilla-daemon at llvm.org
bugzilla-daemon at llvm.org
Mon Apr 20 03:43:53 PDT 2015
https://llvm.org/bugs/show_bug.cgi?id=23293
Bug ID: 23293
Summary: libcxx: racy use-after-free on condition_variable
Product: libc++
Version: unspecified
Hardware: PC
OS: Linux
Status: NEW
Severity: release blocker
Priority: P
Component: All Bugs
Assignee: unassignedclangbugs at nondot.org
Reporter: dvyukov at google.com
CC: llvmbugs at cs.uiuc.edu, mclow.lists at gmail.com
Classification: Unclassified
clang version 3.7.0 (trunk 235293)
Target: x86_64-unknown-linux-gnu
The program is:
#include <iostream>
#include <memory>
#include <future>
#include <atomic>
std::atomic<int> _counter;
int main()
{
_counter = 1;
auto f = std::async(std::launch::async,
[]{
_counter += 2;
return true;
});
std::cout << "Result: " << std::boolalpha << f.get() << "\n";
return 0;
}
ThreadSanitizer says:
==================
WARNING: ThreadSanitizer: data race (pid=19479)
Write of size 8 at 0x7d200000bfc0 by main thread:
#0 pthread_cond_destroy
/ssd/src/llvm/build/../projects/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:1153
(a.out+0x00000044aa8c)
#1 std::__1::condition_variable::~condition_variable()
build/../projects/libcxx/src/condition_variable.cpp:23:5
(libc++.so.1+0x00000008cb69)
#2 std::__1::__assoc_sub_state::~__assoc_sub_state()
build/bin/../include/c++/v1/future:515:24 (a.out+0x00000049999a)
#3 std::__1::__async_assoc_state<bool, std::__1::__async_func<main::$_0>
>::~__async_assoc_state() build/bin/../include/c++/v1/future:940:7
(a.out+0x0000004992d5)
#4 std::__1::__assoc_state<bool>::__on_zero_shared()
build/bin/../include/c++/v1/future:635:5 (a.out+0x000000499a63)
#5 std::__1::__async_assoc_state<bool, std::__1::__async_func<main::$_0>
>::__on_zero_shared() build/bin/../include/c++/v1/future:990:5
(a.out+0x00000049930d)
#6 std::__1::__shared_count::__release_shared()
build/../projects/libcxx/src/memory.cpp:63:9 (libc++.so.1+0x00000008eb20)
#7 std::__1::__release_shared_count::operator()(std::__1::__shared_count*)
build/bin/../include/c++/v1/future:1155:41 (a.out+0x00000049a155)
#8 std::__1::unique_ptr<std::__1::__shared_count,
std::__1::__release_shared_count>::reset(std::__1::__shared_count*)
build/bin/../include/c++/v1/memory:2669:13 (a.out+0x0000004996bd)
#9 std::__1::unique_ptr<std::__1::__shared_count,
std::__1::__release_shared_count>::~unique_ptr()
build/bin/../include/c++/v1/memory:2637 (a.out+0x0000004996bd)
#10 std::__1::future<bool>::get() build/bin/../include/c++/v1/future:1173
(a.out+0x0000004996bd)
#11 main /tmp/shared_ptr.cc:17:50 (a.out+0x000000498f62)
Previous read of size 8 at 0x7d200000bfc0 by thread T1:
#0 pthread_cond_broadcast
/ssd/src/llvm/build/../projects/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:1146
(a.out+0x000000447e40)
#1 std::__1::condition_variable::notify_all()
build/../projects/libcxx/src/condition_variable.cpp:35:5
(libc++.so.1+0x00000008cbc9)
#2 void std::__1::__assoc_state<bool>::set_value<bool>(bool&&)
build/bin/../include/c++/v1/future:655:5 (a.out+0x000000499c01)
#3 std::__1::__async_assoc_state<bool, std::__1::__async_func<main::$_0>
>::__execute() build/bin/../include/c++/v1/future:975:9 (a.out+0x00000049934e)
#4
_ZNSt3__18__invokeIMNS_19__async_assoc_stateIbNS_12__async_funcIZ4mainE3$_0JEEEEEFvvEPS5_JEvEEDTcldsdeclsr3std3__1E7forwardIT0_Efp0_Efp_spclsr3std3__1E7forwardIT1_Efp1_EEEOT_OS9_DpOSA_
build/bin/../include/c++/v1/__functional_base:382:12 (a.out+0x0000004994a1)
#5 void std::__1::__thread_execute<void
(std::__1::__async_assoc_state<bool, std::__1::__async_func<main::$_0> >::*)(),
std::__1::__async_assoc_state<bool, std::__1::__async_func<main::$_0> >*,
1ul>(std::__1::tuple<void (std::__1::__async_assoc_state<bool,
std::__1::__async_func<main::$_0> >::*)(), std::__1::__async_assoc_state<bool,
std::__1::__async_func<main::$_0> >*>&, std::__1::__tuple_indices<1ul>)
build/bin/../include/c++/v1/thread:337 (a.out+0x0000004994a1)
#6 void* std::__1::__thread_proxy<std::__1::tuple<void
(std::__1::__async_assoc_state<bool, std::__1::__async_func<main::$_0> >::*)(),
std::__1::__async_assoc_state<bool, std::__1::__async_func<main::$_0> >*>
>(void*) build/bin/../include/c++/v1/thread:347 (a.out+0x0000004994a1)
Location is heap block of size 120 at 0x7d200000bf80 allocated by main
thread:
#0 operator new(unsigned long)
/ssd/src/llvm/build/../projects/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:615
(a.out+0x00000043e08f)
#1 std::__1::future<bool> std::__1::__make_async_assoc_state<bool,
std::__1::__async_func<main::$_0> >(std::__1::__async_func<main::$_0>&&)
build/bin/../include/c++/v1/future:2312:13 (a.out+0x000000499035)
#2
std::__1::future<std::__1::__invoke_of<std::__1::decay<main::$_0>::type>::type>
std::__1::async<main::$_0>(std::__1::launch, main::$_0&&)
build/bin/../include/c++/v1/future:2361:16 (a.out+0x000000498fce)
#3 main /tmp/shared_ptr.cc:12:14 (a.out+0x000000498f0d)
Thread T1 (tid=19481, finished) created by main thread at:
#0 pthread_create
/ssd/src/llvm/build/../projects/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:951
(a.out+0x000000447123)
#1 std::__1::thread::thread<void (std::__1::__async_assoc_state<bool,
std::__1::__async_func<main::$_0> >::*)(), std::__1::__async_assoc_state<bool,
std::__1::__async_func<main::$_0> >*, void>(void
(std::__1::__async_assoc_state<bool, std::__1::__async_func<main::$_0>
>::*&&)(), std::__1::__async_assoc_state<bool,
std::__1::__async_func<main::$_0> >*&&)
build/bin/../include/c++/v1/thread:359:16 (a.out+0x000000499282)
#2 std::__1::future<bool> std::__1::__make_async_assoc_state<bool,
std::__1::__async_func<main::$_0> >(std::__1::__async_func<main::$_0>&&)
build/bin/../include/c++/v1/future:2313:5 (a.out+0x0000004990a4)
#3
std::__1::future<std::__1::__invoke_of<std::__1::decay<main::$_0>::type>::type>
std::__1::async<main::$_0>(std::__1::launch, main::$_0&&)
build/bin/../include/c++/v1/future:2361:16 (a.out+0x000000498fce)
#4 main /tmp/shared_ptr.cc:12:14 (a.out+0x000000498f0d)
SUMMARY: ThreadSanitizer: data race
build/../projects/libcxx/src/condition_variable.cpp:23:5 in
std::__1::condition_variable::~condition_variable()
==================
The program was built as:
clang++ test.cc -fsanitize=thread -std=c++14 -stdlib=libc++ -lc++abi -Wall -g
-O1
with tsan-instrumented libcxx (see instructions here
https://code.google.com/p/memory-sanitizer/wiki/LibcxxHowTo).
The problem is here:
__assoc_state<_Rp>::set_value(_Arg&& __arg)
{
unique_lock<mutex> __lk(this->__mut_);
#ifndef _LIBCPP_NO_EXCEPTIONS
if (this->__has_value())
throw
future_error(make_error_code(future_errc::promise_already_satisfied));
#endif
::new(&__value_) _Rp(_VSTD::forward<_Arg>(__arg));
this->__state_ |= base::__constructed | base::ready;
__lk.unlock();
__cv_.notify_all();
}
The function first unlocks the mutex and after than signals the cond var. But
once the mutex is unlocked the object can be destroyed as it is in ready state.
--
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20150420/785e1aa2/attachment.html>
More information about the llvm-bugs
mailing list