From: Jonathan Wakely Date: Mon, 2 Jun 2014 15:45:09 +0000 (+0100) Subject: condition_variable (condition_variable_any::_Unlock): Do not swallow __forced_unwind. X-Git-Tag: releases/gcc-5.1.0~7152 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=315eb4bb08abaee794c5f8a924cb4ae0d9fc2c61;p=thirdparty%2Fgcc.git condition_variable (condition_variable_any::_Unlock): Do not swallow __forced_unwind. * 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 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 885718fb5dd8..be5a0fbb93bd 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,14 @@ +2014-06-02 Jonathan Wakely + + * 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 Jonathan Wakely diff --git a/libstdc++-v3/include/std/condition_variable b/libstdc++-v3/include/std/condition_variable index fc111dd3d37c..921cb837de94 100644 --- a/libstdc++-v3/include/std/condition_variable +++ b/libstdc++-v3/include/std/condition_variable @@ -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(); } diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future index ea11f3f03e97..094914448c43 100644 --- a/libstdc++-v3/include/std/future +++ b/libstdc++-v3/include/std/future @@ -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(_M_result)) + this->_M_break_promise(std::move(_M_result)); + __throw_exception_again; + } } }; } diff --git a/libstdc++-v3/include/std/mutex b/libstdc++-v3/include/std/mutex index 3d70754d94be..f6b851c90b08 100644 --- a/libstdc++-v3/include/std/mutex +++ b/libstdc++-v3/include/std/mutex @@ -44,6 +44,7 @@ #include #include #include // for std::swap +#include #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 index 000000000000..7b0a49280fc3 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/async/forced_unwind.cc @@ -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 +// . + +// Test (non-standard) handling of __forced_unwind exception. + +#include +#include +#include +#include + +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 index 000000000000..235ab178f051 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/packaged_task/forced_unwind.cc @@ -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 +// . + +// Test (non-standard) handling of __forced_unwind exception. + +#include +#include +#include +#include + +void f() { pthread_exit(nullptr); } + +int main() +{ + std::packaged_task 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(); +}