[Boost-bugs] [Boost C++ Libraries] #5727: race condition between ~basic_condition_variable() and notify_all()

Subject: [Boost-bugs] [Boost C++ Libraries] #5727: race condition between ~basic_condition_variable() and notify_all()
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2011-07-20 21:53:35


#5727: race condition between ~basic_condition_variable() and notify_all()
------------------------------------+---------------------------------------
 Reporter: sbear.powell@… | Owner: anthonyw
     Type: Bugs | Status: new
Milestone: To Be Determined | Component: thread
  Version: Boost 1.46.1 | Severity: Problem
 Keywords: |
------------------------------------+---------------------------------------
 I was writing a quick parfor function when I found this. I think there's a
 race between ~basic_condition_variable() and notify_all() (notify_one()
 hasn't failed for me). The following code fails an assertion on my
 platform (32 bit MSVC 2010):
 {{{
 void foo() {
     condition_variable notifier;
     mutex m, m2;
     mutex::scoped_lock lock(m);
     bool done=false;
     thread t([&]{
         mutex::scoped_lock lock(m);
         done = true;
         lock.unlock();
         notifier.notify_all();
     });
     while(!done) notifier.wait(lock);
 }
 }}}

 {{{
 "Assertion failed: CloseHandle(handle_to_manage), file
 c:\boost_1_46_1\boost\thread\win32\thread_primitives.hpp, line 237"
 }}}


 A more detailed stack trace says the exception comes from the worker
 thread at:

 {{{
 boost::detail::win32::handle_manager::cleanup()
 boost\thread\win32\thread_primitives.hpp 237:
 BOOST_VERIFY(CloseHandle(handle_to_manage));
 boost::detail::win32::handle_manager::operator=(void *
 new_handle=0x00000000) boost\thread\win32\thread_primitives.hpp 251:
 cleanup();
 boost::detail::basic_condition_variable::notify_all()
 boost\thread\win32\condition_variable.hpp 288:
 wake_sem=detail::win32::handle(0);
 notifier.notify_all();
 ...
 }}}

 My workaround is to add a second mutex to keep foo() from returning before
 notify_all() has returned:

 {{{
 void foo() {
     condition_variable notifier;
     mutex m, m2;
     mutex::scoped_lock lock(m);
     bool done=false;
     thread t([&]{
         mutex::scoped_lock lock(m);
         mutex::scoped_lock lock2(m2);
         done = true;
         lock.unlock();
         notifier.notify_all();
     });
     while(!done) notifier.wait(lock);
     mutex::scoped_lock lock2(m2);
 }
 }}}

 I think (haven't tested) that the real fix is to lock
 basic_condition_variable's internal_mutex in ~basic_condition_variable()
 so that it will block until any concurrently running member functions have
 finished. (an educated guess... this is the first time I've looked at the
 guts of boost.thread)

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/5727>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:07 UTC