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
This commit is contained in:
Jonathan Wakely 2014-06-02 16:45:09 +01:00 committed by Jonathan Wakely
parent d371802725
commit 315eb4bb08
6 changed files with 134 additions and 2 deletions

View 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>

View 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();
}

View 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;
}
} };
}

View 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;

View File

@ -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 );
}
}

View File

@ -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();
}