[libcxx] r233946 - Fix race conditions in test class used throughout the std::thread tests.

Eric Fiselier eric at efcs.ca
Thu Apr 2 14:12:18 PDT 2015


Author: ericwf
Date: Thu Apr  2 16:12:17 2015
New Revision: 233946

URL: http://llvm.org/viewvc/llvm-project?rev=233946&view=rev
Log:
Fix race conditions in test class used throughout the std::thread tests.

The test class 'G' reads and writes to the same static variables in its
constructor, destructor and call operator. When threads are
constructed using `std::thread t((G()))` there is a race condition between the
destruction of the temporary and the execution of `G::operator()()`.

The fix is to simply create the input before creating the thread.

Modified:
    libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.algorithm/swap.pass.cpp
    libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.assign/move.pass.cpp
    libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.assign/move2.pass.cpp
    libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/move.pass.cpp
    libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.destr/dtor.pass.cpp
    libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/get_id.pass.cpp
    libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/join.pass.cpp
    libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/joinable.pass.cpp
    libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/native_handle.pass.cpp
    libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/swap.pass.cpp

Modified: libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.algorithm/swap.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.algorithm/swap.pass.cpp?rev=233946&r1=233945&r2=233946&view=diff
==============================================================================
--- libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.algorithm/swap.pass.cpp (original)
+++ libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.algorithm/swap.pass.cpp Thu Apr  2 16:12:17 2015
@@ -45,7 +45,8 @@ bool G::op_run = false;
 int main()
 {
     {
-        std::thread t0((G()));
+        G g;
+        std::thread t0(g);
         std::thread::id id0 = t0.get_id();
         std::thread t1;
         std::thread::id id1 = t1.get_id();

Modified: libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.assign/move.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.assign/move.pass.cpp?rev=233946&r1=233945&r2=233946&view=diff
==============================================================================
--- libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.assign/move.pass.cpp (original)
+++ libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.assign/move.pass.cpp Thu Apr  2 16:12:17 2015
@@ -48,13 +48,16 @@ int main()
     {
         assert(G::n_alive == 0);
         assert(!G::op_run);
-        std::thread t0(G(), 5, 5.5);
+        {
+        G g;
+        std::thread t0(g, 5, 5.5);
         std::thread::id id = t0.get_id();
         std::thread t1;
         t1 = std::move(t0);
         assert(t1.get_id() == id);
         assert(t0.get_id() == std::thread::id());
         t1.join();
+        }
         assert(G::n_alive == 0);
         assert(G::op_run);
     }

Modified: libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.assign/move2.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.assign/move2.pass.cpp?rev=233946&r1=233945&r2=233946&view=diff
==============================================================================
--- libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.assign/move2.pass.cpp (original)
+++ libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.assign/move2.pass.cpp Thu Apr  2 16:12:17 2015
@@ -13,6 +13,9 @@
 // memory is not freed. This will cause ASAN to fail.
 // XFAIL: asan
 
+// NOTE: TSAN will report this test as leaking a thread.
+// XFAIL: tsan
+
 // <thread>
 
 // class thread
@@ -62,14 +65,13 @@ void f1()
 
 int main()
 {
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
     std::set_terminate(f1);
     {
-        std::thread t0(G(), 5, 5.5);
+        G g;
+        std::thread t0(g, 5, 5.5);
         std::thread::id id = t0.get_id();
         std::thread t1;
         t0 = std::move(t1);
         assert(false);
     }
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
 }

Modified: libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/move.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/move.pass.cpp?rev=233946&r1=233945&r2=233946&view=diff
==============================================================================
--- libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/move.pass.cpp (original)
+++ libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/move.pass.cpp Thu Apr  2 16:12:17 2015
@@ -55,16 +55,18 @@ int main()
 {
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
     {
-        assert(G::n_alive == 0);
+        G g;
+        assert(G::n_alive == 1);
         assert(!G::op_run);
-        std::thread t0(G(), 5, 5.5);
+        std::thread t0(g, 5, 5.5);
         std::thread::id id = t0.get_id();
         std::thread t1 = std::move(t0);
         assert(t1.get_id() == id);
         assert(t0.get_id() == std::thread::id());
         t1.join();
-        assert(G::n_alive == 0);
+        assert(G::n_alive == 1);
         assert(G::op_run);
     }
+    assert(G::n_alive == 0);
 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
 }

Modified: libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.destr/dtor.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.destr/dtor.pass.cpp?rev=233946&r1=233945&r2=233946&view=diff
==============================================================================
--- libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.destr/dtor.pass.cpp (original)
+++ libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.destr/dtor.pass.cpp Thu Apr  2 16:12:17 2015
@@ -9,6 +9,9 @@
 //
 // UNSUPPORTED: libcpp-has-no-threads
 
+// NOTE: TSAN will report this test as leaking a thread.
+// XFAIL: tsan
+
 // <thread>
 
 // class thread
@@ -53,8 +56,11 @@ int main()
     {
         assert(G::n_alive == 0);
         assert(!G::op_run);
-        std::thread t((G()));
-        std::this_thread::sleep_for(std::chrono::milliseconds(250));
+        G g;
+        {
+          std::thread t(g);
+          std::this_thread::sleep_for(std::chrono::milliseconds(250));
+        }
     }
     assert(false);
 }

Modified: libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/get_id.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/get_id.pass.cpp?rev=233946&r1=233945&r2=233946&view=diff
==============================================================================
--- libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/get_id.pass.cpp (original)
+++ libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/get_id.pass.cpp Thu Apr  2 16:12:17 2015
@@ -45,7 +45,8 @@ bool G::op_run = false;
 int main()
 {
     {
-        std::thread t0((G()));
+        G g;
+        std::thread t0(g);
         std::thread::id id0 = t0.get_id();
         std::thread t1;
         std::thread::id id1 = t1.get_id();

Modified: libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/join.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/join.pass.cpp?rev=233946&r1=233945&r2=233946&view=diff
==============================================================================
--- libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/join.pass.cpp (original)
+++ libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/join.pass.cpp Thu Apr  2 16:12:17 2015
@@ -45,7 +45,8 @@ bool G::op_run = false;
 int main()
 {
     {
-        std::thread t0((G()));
+        G g;
+        std::thread t0(g);
         assert(t0.joinable());
         t0.join();
         assert(!t0.joinable());

Modified: libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/joinable.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/joinable.pass.cpp?rev=233946&r1=233945&r2=233946&view=diff
==============================================================================
--- libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/joinable.pass.cpp (original)
+++ libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/joinable.pass.cpp Thu Apr  2 16:12:17 2015
@@ -45,7 +45,8 @@ bool G::op_run = false;
 int main()
 {
     {
-        std::thread t0((G()));
+        G g;
+        std::thread t0(g);
         assert(t0.joinable());
         t0.join();
         assert(!t0.joinable());

Modified: libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/native_handle.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/native_handle.pass.cpp?rev=233946&r1=233945&r2=233946&view=diff
==============================================================================
--- libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/native_handle.pass.cpp (original)
+++ libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/native_handle.pass.cpp Thu Apr  2 16:12:17 2015
@@ -45,7 +45,8 @@ bool G::op_run = false;
 int main()
 {
     {
-        std::thread t0((G()));
+        G g;
+        std::thread t0(g);
         pthread_t pid = t0.native_handle();
         assert(pid != 0);
         t0.join();

Modified: libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/swap.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/swap.pass.cpp?rev=233946&r1=233945&r2=233946&view=diff
==============================================================================
--- libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/swap.pass.cpp (original)
+++ libcxx/trunk/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/swap.pass.cpp Thu Apr  2 16:12:17 2015
@@ -45,7 +45,8 @@ bool G::op_run = false;
 int main()
 {
     {
-        std::thread t0((G()));
+        G g;
+        std::thread t0(g);
         std::thread::id id0 = t0.get_id();
         std::thread t1;
         std::thread::id id1 = t1.get_id();





More information about the cfe-commits mailing list