]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
condition_variable (condition_variable_any::_Unlock): Do not swallow __forced_unwind.
authorJonathan Wakely <jwakely@redhat.com>
Mon, 2 Jun 2014 15:45:09 +0000 (16:45 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Mon, 2 Jun 2014 15:45:09 +0000 (16:45 +0100)
* include/std/condition_variable (condition_variable_any::_Unlock): Do
not swallow __forced_unwind.
* include/std/future (__future_base::_Task_setter): Likewise.
(__future_base::_Async_state_impl): Turn __forced_unwind into broken
promise and rethrow.
* include/std/mutex (try_lock): Likewise.
* testsuite/30_threads/async/forced_unwind.cc: New.
* testsuite/30_threads/packaged_task/forced_unwind.cc: New.

From-SVN: r211138

libstdc++-v3/ChangeLog
libstdc++-v3/include/std/condition_variable
libstdc++-v3/include/std/future
libstdc++-v3/include/std/mutex
libstdc++-v3/testsuite/30_threads/async/forced_unwind.cc [new file with mode: 0644]
libstdc++-v3/testsuite/30_threads/packaged_task/forced_unwind.cc [new file with mode: 0644]

index 885718fb5dd8d77c7408aee272c5e358bbbca807..be5a0fbb93bd33aa5976313a9af7a395dd6a8bd5 100644 (file)
@@ -1,3 +1,14 @@
+2014-06-02  Jonathan Wakely  <jwakely@redhat.com>
+
+       * include/std/condition_variable (condition_variable_any::_Unlock): Do
+       not swallow __forced_unwind.
+       * include/std/future (__future_base::_Task_setter): Likewise.
+       (__future_base::_Async_state_impl): Turn __forced_unwind into broken
+       promise and rethrow.
+       * include/std/mutex (try_lock): Likewise.
+       * testsuite/30_threads/async/forced_unwind.cc: New.
+       * testsuite/30_threads/packaged_task/forced_unwind.cc: New.
+
 2014-06-02  RĂ¼diger Sonderfeld  <ruediger@c-plusplus.de>
            Jonathan Wakely  <jwakely@redhat.com>
 
index fc111dd3d37cdf33f40fc26039481138710619e3..921cb837de94c2dc920fea8d2aa026accf43fb85 100644 (file)
@@ -189,7 +189,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        ~_Unlock() noexcept(false)
        {
          if (uncaught_exception())
-           __try { _M_lock.lock(); } __catch(...) { }
+           {
+             __try
+             { _M_lock.lock(); }
+             __catch(const __cxxabiv1::__forced_unwind&)
+             { __throw_exception_again; }
+             __catch(...)
+             { }
+           }
          else
            _M_lock.lock();
        }
index ea11f3f03e970292bff4fa87c9e4c9367d4367bc..094914448c43475c34919033cf8b48fb4e6518eb 100644 (file)
@@ -1230,6 +1230,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          {
            _M_result->_M_set(_M_fn());
          }
+       __catch(const __cxxabiv1::__forced_unwind&)
+         {
+           __throw_exception_again; // will cause broken_promise
+         }
        __catch(...)
          {
            _M_result->_M_error = current_exception();
@@ -1249,6 +1253,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          {
            _M_fn();
          }
+       __catch(const __cxxabiv1::__forced_unwind&)
+         {
+           __throw_exception_again; // will cause broken_promise
+         }
        __catch(...)
          {
            _M_result->_M_error = current_exception();
@@ -1509,7 +1517,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       : _M_result(new _Result<_Res>()), _M_fn(std::move(__fn))
       {
        _M_thread = std::thread{ [this] {
-         _M_set_result(_S_task_setter(_M_result, _M_fn));
+           __try
+             {
+               _M_set_result(_S_task_setter(_M_result, _M_fn));
+             }
+           __catch (const __cxxabiv1::__forced_unwind&)
+             {
+               // make the shared state ready on thread cancellation
+               if (static_cast<bool>(_M_result))
+                 this->_M_break_promise(std::move(_M_result));
+               __throw_exception_again;
+             }
         } };
       }
 
index 3d70754d94bef49b1f8144d9f16ce85d33222d85..f6b851c90b0844d97fbf7a0093e4222dec93a44e 100644 (file)
@@ -44,6 +44,7 @@
 #include <bits/functexcept.h>
 #include <bits/gthr.h>
 #include <bits/move.h> // for std::swap
+#include <bits/cxxabi_forced.h>
 
 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
 
@@ -631,6 +632,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       auto __locks = std::tie(__l1, __l2, __l3...);
       __try
       { __try_lock_impl<0>::__do_try_lock(__locks, __idx); }
+      __catch(const __cxxabiv1::__forced_unwind&)
+      { __throw_exception_again; }
       __catch(...)
       { }
       return __idx;
diff --git a/libstdc++-v3/testsuite/30_threads/async/forced_unwind.cc b/libstdc++-v3/testsuite/30_threads/async/forced_unwind.cc
new file mode 100644 (file)
index 0000000..7b0a492
--- /dev/null
@@ -0,0 +1,45 @@
+// { dg-do run { target *-*-linux* *-*-gnu* } }
+// { dg-options " -std=gnu++11 -pthread" { target *-*-linux* *-*-gnu* } }
+// { dg-require-cstdint "" }
+// { dg-require-gthreads "" }
+// { dg-require-atomic-builtins "" }
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Test (non-standard) handling of __forced_unwind exception.
+
+#include <future>
+#include <stdexcept>
+#include <pthread.h>
+#include <testsuite_hooks.h>
+
+void f() { pthread_exit(nullptr); }
+
+int main()
+{
+  auto fut = std::async(std::launch::async, f);
+  try
+  {
+    fut.get();
+    throw std::logic_error("Unreachable");
+  }
+  catch (const std::future_error& e)
+  {
+    VERIFY( e.code() == std::future_errc::broken_promise );
+  }
+}
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/forced_unwind.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/forced_unwind.cc
new file mode 100644 (file)
index 0000000..235ab17
--- /dev/null
@@ -0,0 +1,48 @@
+// { dg-do run { target *-*-linux* *-*-gnu* } }
+// { dg-options " -std=gnu++11 -pthread" { target *-*-linux* *-*-gnu* } }
+// { dg-require-cstdint "" }
+// { dg-require-gthreads "" }
+// { dg-require-atomic-builtins "" }
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Test (non-standard) handling of __forced_unwind exception.
+
+#include <future>
+#include <stdexcept>
+#include <pthread.h>
+#include <testsuite_hooks.h>
+
+void f() { pthread_exit(nullptr); }
+
+int main()
+{
+  std::packaged_task<void()> p(f);
+  auto fut = p.get_future();
+  std::thread t(std::move(p));
+  try
+  {
+    fut.get();
+    throw std::logic_error("Unreachable");
+  }
+  catch (const std::future_error& e)
+  {
+    VERIFY( e.code() == std::future_errc::broken_promise );
+  }
+  t.join();
+}