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