Hi mclow.lists, danalbert, jroelofs,
There is a race condition in ASAN where it can perform the leak detection
before all detached threads exit and free their resources. This can lead to
failures in the future tests.
This patch fixes the race condition my manually joining all threads that are
used. This patch should not affect the functionality of the tests.
http://reviews.llvm.org/D6347
Files:
test/thread/futures/futures.shared_future/get.pass.cpp
test/thread/futures/futures.shared_future/wait.pass.cpp
test/thread/futures/futures.shared_future/wait_for.pass.cpp
test/thread/futures/futures.shared_future/wait_until.pass.cpp
test/thread/futures/futures.tas/futures.task.members/dtor.pass.cpp
test/thread/futures/futures.tas/futures.task.members/make_ready_at_thread_exit.pass.cpp
test/thread/futures/futures.tas/futures.task.members/operator.pass.cpp
test/thread/futures/futures.unique_future/get.pass.cpp
test/thread/futures/futures.unique_future/wait.pass.cpp
test/thread/futures/futures.unique_future/wait_for.pass.cpp
test/thread/futures/futures.unique_future/wait_until.pass.cpp
Index: test/thread/futures/futures.shared_future/get.pass.cpp
===================================================================
--- test/thread/futures/futures.shared_future/get.pass.cpp
+++ test/thread/futures/futures.shared_future/get.pass.cpp
@@ -66,15 +66,16 @@
{
std::promise<T> p;
std::shared_future<T> f = p.get_future();
- std::thread(func1, std::move(p)).detach();
+ std::thread t(func1, std::move(p));
assert(f.valid());
assert(f.get() == 3);
assert(f.valid());
+ t.join();
}
{
std::promise<T> p;
std::shared_future<T> f = p.get_future();
- std::thread(func2, std::move(p)).detach();
+ std::thread t(func2, std::move(p));
try
{
assert(f.valid());
@@ -86,22 +87,24 @@
assert(i == 3);
}
assert(f.valid());
+ t.join();
}
}
{
typedef int& T;
{
std::promise<T> p;
std::shared_future<T> f = p.get_future();
- std::thread(func3, std::move(p)).detach();
+ std::thread t(func3, std::move(p));
assert(f.valid());
assert(f.get() == 5);
assert(f.valid());
+ t.join();
}
{
std::promise<T> p;
std::shared_future<T> f = p.get_future();
- std::thread(func4, std::move(p)).detach();
+ std::thread t(func4, std::move(p));
try
{
assert(f.valid());
@@ -113,22 +116,24 @@
assert(i == 3.5);
}
assert(f.valid());
+ t.join();
}
}
{
typedef void T;
{
std::promise<T> p;
std::shared_future<T> f = p.get_future();
- std::thread(func5, std::move(p)).detach();
+ std::thread t(func5, std::move(p));
assert(f.valid());
f.get();
assert(f.valid());
+ t.join();
}
{
std::promise<T> p;
std::shared_future<T> f = p.get_future();
- std::thread(func6, std::move(p)).detach();
+ std::thread t(func6, std::move(p));
try
{
assert(f.valid());
@@ -140,6 +145,7 @@
assert(i == 'c');
}
assert(f.valid());
+ t.join();
}
}
}
Index: test/thread/futures/futures.shared_future/wait.pass.cpp
===================================================================
--- test/thread/futures/futures.shared_future/wait.pass.cpp
+++ test/thread/futures/futures.shared_future/wait.pass.cpp
@@ -47,42 +47,45 @@
typedef int T;
std::promise<T> p;
std::shared_future<T> f = p.get_future();
- std::thread(func1, std::move(p)).detach();
+ std::thread t(func1, std::move(p));
assert(f.valid());
f.wait();
assert(f.valid());
Clock::time_point t0 = Clock::now();
f.wait();
Clock::time_point t1 = Clock::now();
assert(f.valid());
assert(t1-t0 < ms(5));
+ t.join();
}
{
typedef int& T;
std::promise<T> p;
std::shared_future<T> f = p.get_future();
- std::thread(func3, std::move(p)).detach();
+ std::thread t(func3, std::move(p));
assert(f.valid());
f.wait();
assert(f.valid());
Clock::time_point t0 = Clock::now();
f.wait();
Clock::time_point t1 = Clock::now();
assert(f.valid());
assert(t1-t0 < ms(5));
+ t.join();
}
{
typedef void T;
std::promise<T> p;
std::shared_future<T> f = p.get_future();
- std::thread(func5, std::move(p)).detach();
+ std::thread t(func5, std::move(p));
assert(f.valid());
f.wait();
assert(f.valid());
Clock::time_point t0 = Clock::now();
f.wait();
Clock::time_point t1 = Clock::now();
assert(f.valid());
assert(t1-t0 < ms(5));
+ t.join();
}
}
Index: test/thread/futures/futures.shared_future/wait_for.pass.cpp
===================================================================
--- test/thread/futures/futures.shared_future/wait_for.pass.cpp
+++ test/thread/futures/futures.shared_future/wait_for.pass.cpp
@@ -50,7 +50,7 @@
typedef int T;
std::promise<T> p;
std::shared_future<T> f = p.get_future();
- std::thread(func1, std::move(p)).detach();
+ std::thread t(func1, std::move(p));
assert(f.valid());
assert(f.wait_for(ms(300)) == std::future_status::timeout);
assert(f.valid());
@@ -61,12 +61,13 @@
Clock::time_point t1 = Clock::now();
assert(f.valid());
assert(t1-t0 < ms(5));
+ t.join();
}
{
typedef int& T;
std::promise<T> p;
std::shared_future<T> f = p.get_future();
- std::thread(func3, std::move(p)).detach();
+ std::thread t(func3, std::move(p));
assert(f.valid());
assert(f.wait_for(ms(300)) == std::future_status::timeout);
assert(f.valid());
@@ -77,12 +78,13 @@
Clock::time_point t1 = Clock::now();
assert(f.valid());
assert(t1-t0 < ms(5));
+ t.join();
}
{
typedef void T;
std::promise<T> p;
std::shared_future<T> f = p.get_future();
- std::thread(func5, std::move(p)).detach();
+ std::thread t(func5, std::move(p));
assert(f.valid());
assert(f.wait_for(ms(300)) == std::future_status::timeout);
assert(f.valid());
@@ -93,5 +95,6 @@
Clock::time_point t1 = Clock::now();
assert(f.valid());
assert(t1-t0 < ms(5));
+ t.join();
}
}
Index: test/thread/futures/futures.shared_future/wait_until.pass.cpp
===================================================================
--- test/thread/futures/futures.shared_future/wait_until.pass.cpp
+++ test/thread/futures/futures.shared_future/wait_until.pass.cpp
@@ -50,7 +50,7 @@
typedef int T;
std::promise<T> p;
std::shared_future<T> f = p.get_future();
- std::thread(func1, std::move(p)).detach();
+ std::thread t(func1, std::move(p));
assert(f.valid());
assert(f.wait_until(Clock::now() + ms(300)) == std::future_status::timeout);
assert(f.valid());
@@ -61,12 +61,13 @@
Clock::time_point t1 = Clock::now();
assert(f.valid());
assert(t1-t0 < ms(5));
+ t.join();
}
{
typedef int& T;
std::promise<T> p;
std::shared_future<T> f = p.get_future();
- std::thread(func3, std::move(p)).detach();
+ std::thread t(func3, std::move(p));
assert(f.valid());
assert(f.wait_until(Clock::now() + ms(300)) == std::future_status::timeout);
assert(f.valid());
@@ -77,12 +78,13 @@
Clock::time_point t1 = Clock::now();
assert(f.valid());
assert(t1-t0 < ms(5));
+ t.join();
}
{
typedef void T;
std::promise<T> p;
std::shared_future<T> f = p.get_future();
- std::thread(func5, std::move(p)).detach();
+ std::thread t(func5, std::move(p));
assert(f.valid());
assert(f.wait_until(Clock::now() + ms(300)) == std::future_status::timeout);
assert(f.valid());
@@ -93,5 +95,6 @@
Clock::time_point t1 = Clock::now();
assert(f.valid());
assert(t1-t0 < ms(5));
+ t.join();
}
}
Index: test/thread/futures/futures.tas/futures.task.members/dtor.pass.cpp
===================================================================
--- test/thread/futures/futures.tas/futures.task.members/dtor.pass.cpp
+++ test/thread/futures/futures.tas/futures.task.members/dtor.pass.cpp
@@ -42,7 +42,7 @@
{
std::packaged_task<double(int, char)> p(A(5));
std::future<double> f = p.get_future();
- std::thread(func, std::move(p)).detach();
+ std::thread t(func, std::move(p));
try
{
double i = f.get();
@@ -52,11 +52,13 @@
{
assert(e.code() == make_error_code(std::future_errc::broken_promise));
}
+ t.join();
}
{
std::packaged_task<double(int, char)> p(A(5));
std::future<double> f = p.get_future();
- std::thread(func2, std::move(p)).detach();
+ std::thread t(func2, std::move(p));
assert(f.get() == 105.0);
+ t.join();
}
}
Index: test/thread/futures/futures.tas/futures.task.members/make_ready_at_thread_exit.pass.cpp
===================================================================
--- test/thread/futures/futures.tas/futures.task.members/make_ready_at_thread_exit.pass.cpp
+++ test/thread/futures/futures.tas/futures.task.members/make_ready_at_thread_exit.pass.cpp
@@ -75,13 +75,14 @@
{
std::packaged_task<double(int, char)> p(A(5));
std::future<double> f = p.get_future();
- std::thread(func0, std::move(p)).detach();
+ std::thread t(func0, std::move(p));
assert(f.get() == 105.0);
+ t.join();
}
{
std::packaged_task<double(int, char)> p(A(5));
std::future<double> f = p.get_future();
- std::thread(func1, std::move(p)).detach();
+ std::thread t(func1, std::move(p));
try
{
f.get();
@@ -91,12 +92,14 @@
{
assert(e(3, 'a') == 106);
}
+ t.join();
}
{
std::packaged_task<double(int, char)> p(A(5));
std::future<double> f = p.get_future();
- std::thread(func2, std::move(p)).detach();
+ std::thread t(func2, std::move(p));
assert(f.get() == 105.0);
+ t.join();
}
{
std::packaged_task<double(int, char)> p;
Index: test/thread/futures/futures.tas/futures.task.members/operator.pass.cpp
===================================================================
--- test/thread/futures/futures.tas/futures.task.members/operator.pass.cpp
+++ test/thread/futures/futures.tas/futures.task.members/operator.pass.cpp
@@ -75,13 +75,14 @@
{
std::packaged_task<double(int, char)> p(A(5));
std::future<double> f = p.get_future();
- std::thread(func0, std::move(p)).detach();
+ std::thread t(func0, std::move(p));
assert(f.get() == 105.0);
+ t.join();
}
{
std::packaged_task<double(int, char)> p(A(5));
std::future<double> f = p.get_future();
- std::thread(func1, std::move(p)).detach();
+ std::thread t(func1, std::move(p));
try
{
f.get();
@@ -91,6 +92,7 @@
{
assert(e(3, 'a') == 106);
}
+ t.join();
}
{
std::packaged_task<double(int, char)> p(A(5));
Index: test/thread/futures/futures.unique_future/get.pass.cpp
===================================================================
--- test/thread/futures/futures.unique_future/get.pass.cpp
+++ test/thread/futures/futures.unique_future/get.pass.cpp
@@ -66,15 +66,16 @@
{
std::promise<T> p;
std::future<T> f = p.get_future();
- std::thread(func1, std::move(p)).detach();
+ std::thread t(func1, std::move(p));
assert(f.valid());
assert(f.get() == 3);
assert(!f.valid());
+ t.join();
}
{
std::promise<T> p;
std::future<T> f = p.get_future();
- std::thread(func2, std::move(p)).detach();
+ std::thread t(func2, std::move(p));
try
{
assert(f.valid());
@@ -86,22 +87,24 @@
assert(i == 3);
}
assert(!f.valid());
+ t.join();
}
}
{
typedef int& T;
{
std::promise<T> p;
std::future<T> f = p.get_future();
- std::thread(func3, std::move(p)).detach();
+ std::thread t(func3, std::move(p));
assert(f.valid());
assert(f.get() == 5);
assert(!f.valid());
+ t.join();
}
{
std::promise<T> p;
std::future<T> f = p.get_future();
- std::thread(func4, std::move(p)).detach();
+ std::thread t(func4, std::move(p));
try
{
assert(f.valid());
@@ -113,22 +116,24 @@
assert(i == 3.5);
}
assert(!f.valid());
+ t.join();
}
}
{
typedef void T;
{
std::promise<T> p;
std::future<T> f = p.get_future();
- std::thread(func5, std::move(p)).detach();
+ std::thread t(func5, std::move(p));
assert(f.valid());
f.get();
assert(!f.valid());
+ t.join();
}
{
std::promise<T> p;
std::future<T> f = p.get_future();
- std::thread(func6, std::move(p)).detach();
+ std::thread t(func6, std::move(p));
try
{
assert(f.valid());
@@ -140,6 +145,7 @@
assert(i == 'c');
}
assert(!f.valid());
+ t.join();
}
}
}
Index: test/thread/futures/futures.unique_future/wait.pass.cpp
===================================================================
--- test/thread/futures/futures.unique_future/wait.pass.cpp
+++ test/thread/futures/futures.unique_future/wait.pass.cpp
@@ -47,42 +47,45 @@
typedef int T;
std::promise<T> p;
std::future<T> f = p.get_future();
- std::thread(func1, std::move(p)).detach();
+ std::thread t(func1, std::move(p));
assert(f.valid());
f.wait();
assert(f.valid());
Clock::time_point t0 = Clock::now();
f.wait();
Clock::time_point t1 = Clock::now();
assert(f.valid());
assert(t1-t0 < ms(5));
+ t.join();
}
{
typedef int& T;
std::promise<T> p;
std::future<T> f = p.get_future();
- std::thread(func3, std::move(p)).detach();
+ std::thread t(func3, std::move(p));
assert(f.valid());
f.wait();
assert(f.valid());
Clock::time_point t0 = Clock::now();
f.wait();
Clock::time_point t1 = Clock::now();
assert(f.valid());
assert(t1-t0 < ms(5));
+ t.join();
}
{
typedef void T;
std::promise<T> p;
std::future<T> f = p.get_future();
- std::thread(func5, std::move(p)).detach();
+ std::thread t(func5, std::move(p));
assert(f.valid());
f.wait();
assert(f.valid());
Clock::time_point t0 = Clock::now();
f.wait();
Clock::time_point t1 = Clock::now();
assert(f.valid());
assert(t1-t0 < ms(5));
+ t.join();
}
}
Index: test/thread/futures/futures.unique_future/wait_for.pass.cpp
===================================================================
--- test/thread/futures/futures.unique_future/wait_for.pass.cpp
+++ test/thread/futures/futures.unique_future/wait_for.pass.cpp
@@ -50,7 +50,7 @@
typedef int T;
std::promise<T> p;
std::future<T> f = p.get_future();
- std::thread(func1, std::move(p)).detach();
+ std::thread t(func1, std::move(p));
assert(f.valid());
assert(f.wait_for(ms(300)) == std::future_status::timeout);
assert(f.valid());
@@ -61,12 +61,13 @@
Clock::time_point t1 = Clock::now();
assert(f.valid());
assert(t1-t0 < ms(50));
+ t.join();
}
{
typedef int& T;
std::promise<T> p;
std::future<T> f = p.get_future();
- std::thread(func3, std::move(p)).detach();
+ std::thread t(func3, std::move(p));
assert(f.valid());
assert(f.wait_for(ms(300)) == std::future_status::timeout);
assert(f.valid());
@@ -77,12 +78,13 @@
Clock::time_point t1 = Clock::now();
assert(f.valid());
assert(t1-t0 < ms(50));
+ t.join();
}
{
typedef void T;
std::promise<T> p;
std::future<T> f = p.get_future();
- std::thread(func5, std::move(p)).detach();
+ std::thread t(func5, std::move(p));
assert(f.valid());
assert(f.wait_for(ms(300)) == std::future_status::timeout);
assert(f.valid());
@@ -93,5 +95,6 @@
Clock::time_point t1 = Clock::now();
assert(f.valid());
assert(t1-t0 < ms(50));
+ t.join();
}
}
Index: test/thread/futures/futures.unique_future/wait_until.pass.cpp
===================================================================
--- test/thread/futures/futures.unique_future/wait_until.pass.cpp
+++ test/thread/futures/futures.unique_future/wait_until.pass.cpp
@@ -50,7 +50,7 @@
typedef int T;
std::promise<T> p;
std::future<T> f = p.get_future();
- std::thread(func1, std::move(p)).detach();
+ std::thread t(func1, std::move(p));
assert(f.valid());
assert(f.wait_until(Clock::now() + ms(300)) == std::future_status::timeout);
assert(f.valid());
@@ -61,12 +61,13 @@
Clock::time_point t1 = Clock::now();
assert(f.valid());
assert(t1-t0 < ms(5));
+ t.join();
}
{
typedef int& T;
std::promise<T> p;
std::future<T> f = p.get_future();
- std::thread(func3, std::move(p)).detach();
+ std::thread t(func3, std::move(p));
assert(f.valid());
assert(f.wait_until(Clock::now() + ms(300)) == std::future_status::timeout);
assert(f.valid());
@@ -77,12 +78,13 @@
Clock::time_point t1 = Clock::now();
assert(f.valid());
assert(t1-t0 < ms(5));
+ t.join();
}
{
typedef void T;
std::promise<T> p;
std::future<T> f = p.get_future();
- std::thread(func5, std::move(p)).detach();
+ std::thread t(func5, std::move(p));
assert(f.valid());
assert(f.wait_until(Clock::now() + ms(300)) == std::future_status::timeout);
assert(f.valid());
@@ -93,5 +95,6 @@
Clock::time_point t1 = Clock::now();
assert(f.valid());
assert(t1-t0 < ms(5));
+ t.join();
}
}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits