CaseyCarter created this revision.
CaseyCarter added reviewers: mclow.lists, EricWF.

Drive-by:

- Fix potential race between check and update of `throw_one` in operator new
- Fix latent bug in operator delete, which shouldn't decrement 
`outstanding_new` when passed a null pointer
- Specifically catch the expected `bad_alloc` in `main` instead of `...`


https://reviews.llvm.org/D50860

Files:
  
test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp


Index: 
test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp
===================================================================
--- 
test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp
+++ 
test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp
@@ -31,17 +31,19 @@
 
 void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc)
 {
-    if (throw_one == 0)
-        TEST_THROW(std::bad_alloc());
-    --throw_one;
+    unsigned expected = throw_one;
+    do {
+        if (expected == 0) TEST_THROW(std::bad_alloc());
+    } while (!throw_one.compare_exchange_weak(expected, expected - 1));
     ++outstanding_new;
     void* ret = std::malloc(s);
     if (!ret) std::abort(); // placate MSVC's unchecked malloc warning
     return ret;
 }
 
 void  operator delete(void* p) TEST_NOEXCEPT
 {
+    if (!p) return;
     --outstanding_new;
     std::free(p);
 }
@@ -116,14 +118,16 @@
 //    2.3 Check that no memory allocated by the creation of the thread is 
leaked.
 //  3 Finally check that a thread runs successfully if we throw after 'N+1'
 //    allocations.
+int numAllocs;
+
 void test_throwing_new_during_thread_creation() {
 #ifndef TEST_HAS_NO_EXCEPTIONS
     throw_one = 0xFFF;
     {
         std::thread t(f);
         t.join();
     }
-    const int numAllocs = 0xFFF - throw_one;
+    numAllocs = 0xFFF - throw_one;
     // i <= numAllocs means the last iteration is expected not to throw.
     for (int i=0; i <= numAllocs; ++i) {
         throw_one = i;
@@ -164,16 +168,16 @@
     }
     G::op_run = false;
 #ifndef TEST_HAS_NO_EXCEPTIONS
-    {
+    if (numAllocs > 0) {
         try
         {
             throw_one = 0;
             assert(G::n_alive == 0);
             assert(!G::op_run);
             std::thread t((G()));
             assert(false);
         }
-        catch (...)
+        catch (std::bad_alloc const&)
         {
             throw_one = 0xFFFF;
             assert(G::n_alive == 0);


Index: test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp
===================================================================
--- test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp
+++ test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp
@@ -31,17 +31,19 @@
 
 void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc)
 {
-    if (throw_one == 0)
-        TEST_THROW(std::bad_alloc());
-    --throw_one;
+    unsigned expected = throw_one;
+    do {
+        if (expected == 0) TEST_THROW(std::bad_alloc());
+    } while (!throw_one.compare_exchange_weak(expected, expected - 1));
     ++outstanding_new;
     void* ret = std::malloc(s);
     if (!ret) std::abort(); // placate MSVC's unchecked malloc warning
     return ret;
 }
 
 void  operator delete(void* p) TEST_NOEXCEPT
 {
+    if (!p) return;
     --outstanding_new;
     std::free(p);
 }
@@ -116,14 +118,16 @@
 //    2.3 Check that no memory allocated by the creation of the thread is leaked.
 //  3 Finally check that a thread runs successfully if we throw after 'N+1'
 //    allocations.
+int numAllocs;
+
 void test_throwing_new_during_thread_creation() {
 #ifndef TEST_HAS_NO_EXCEPTIONS
     throw_one = 0xFFF;
     {
         std::thread t(f);
         t.join();
     }
-    const int numAllocs = 0xFFF - throw_one;
+    numAllocs = 0xFFF - throw_one;
     // i <= numAllocs means the last iteration is expected not to throw.
     for (int i=0; i <= numAllocs; ++i) {
         throw_one = i;
@@ -164,16 +168,16 @@
     }
     G::op_run = false;
 #ifndef TEST_HAS_NO_EXCEPTIONS
-    {
+    if (numAllocs > 0) {
         try
         {
             throw_one = 0;
             assert(G::n_alive == 0);
             assert(!G::op_run);
             std::thread t((G()));
             assert(false);
         }
-        catch (...)
+        catch (std::bad_alloc const&)
         {
             throw_one = 0xFFFF;
             assert(G::n_alive == 0);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to