From 16ec0602fb1913644bd05e0a783d6f00b517d840 Mon Sep 17 00:00:00 2001 From: redi Date: Tue, 25 Oct 2011 20:56:43 +0000 Subject: [PATCH 1/1] PR libstdc++/50862 * include/std/condition_variable (condition_variable_any::wait): Fix deadlock and ensure _Lock::lock() is called on exit. (condition_variable_any::native_handle): Remove, as per LWG 1500. * testsuite/30_threads/condition_variable_any/50862.cc: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@180446 138bc75d-0d04-0410-961f-82ee72b054a4 --- libstdc++-v3/ChangeLog | 8 +++ libstdc++-v3/include/std/condition_variable | 21 +++--- .../30_threads/condition_variable_any/50862.cc | 75 ++++++++++++++++++++++ 3 files changed, 96 insertions(+), 8 deletions(-) create mode 100644 libstdc++-v3/testsuite/30_threads/condition_variable_any/50862.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index a7d5335b51a..a35ae193f47 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,13 @@ 2011-10-25 Jonathan Wakely + PR libstdc++/50862 + * include/std/condition_variable (condition_variable_any::wait): Fix + deadlock and ensure _Lock::lock() is called on exit. + (condition_variable_any::native_handle): Remove, as per LWG 1500. + * testsuite/30_threads/condition_variable_any/50862.cc: New. + +2011-10-25 Jonathan Wakely + PR libstdc++/49894 * include/std/mutex (__mutex_base,__recursive_mutex_base): Define new base classes to manage construction/destruction of native mutexes, diff --git a/libstdc++-v3/include/std/condition_variable b/libstdc++-v3/include/std/condition_variable index ef22a1dbf02..e17f3263568 100644 --- a/libstdc++-v3/include/std/condition_variable +++ b/libstdc++-v3/include/std/condition_variable @@ -203,10 +203,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void wait(_Lock& __lock) { - unique_lock __my_lock(_M_mutex); - __lock.unlock(); - _M_cond.wait(__my_lock); - __lock.lock(); + // scoped unlock - unlocks in ctor, re-locks in dtor + struct _Unlock { + explicit _Unlock(_Lock& __lk) : _M_lock(__lk) { __lk.unlock(); } + ~_Unlock() { _M_lock.lock(); } + _Lock& _M_lock; + }; + + unique_lock __my_lock(_M_mutex); + _Unlock __unlock(__lock); + // _M_mutex must be unlocked before re-locking __lock so move + // ownership of _M_mutex lock to an object with shorter lifetime. + unique_lock __my_lock2(std::move(__my_lock)); + _M_cond.wait(__my_lock2); } @@ -254,10 +263,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION wait_for(_Lock& __lock, const chrono::duration<_Rep, _Period>& __rtime, _Predicate __p) { return wait_until(__lock, __clock_t::now() + __rtime, std::move(__p)); } - - native_handle_type - native_handle() - { return _M_cond.native_handle(); } }; // @} group condition_variables diff --git a/libstdc++-v3/testsuite/30_threads/condition_variable_any/50862.cc b/libstdc++-v3/testsuite/30_threads/condition_variable_any/50862.cc new file mode 100644 index 00000000000..db2a5eb71b2 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/condition_variable_any/50862.cc @@ -0,0 +1,75 @@ +// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* alpha*-*-osf* mips-sgi-irix6* } } +// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* alpha*-*-osf* mips-sgi-irix6* } } +// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } } +// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } } +// { dg-require-cstdint "" } +// { dg-require-gthreads "" } + +// Copyright (C) 2011 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 +// . + +#include +#include +#include +#include +#include + +struct scoped_thread +{ + ~scoped_thread() { if (t.joinable()) t.join(); } + std::thread t; +}; + +int main() +{ + typedef std::unique_lock Lock; + + std::mutex m; + std::condition_variable_any cond; + unsigned int product=0; + const unsigned int count=10; + + // writing to stream causes timing changes which makes deadlock easier + // to reproduce - do not remove + std::ostringstream out; + + // create consumers + std::array threads; + for(size_t i=0; i