Subject: [Boost-bugs] [Boost C++ Libraries] #5432: Deadlock with thread group's join_all and other modifier methods.
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2011-04-06 13:45:02
#5432: Deadlock with thread group's join_all and other modifier methods.
------------------------------+---------------------------------------------
Reporter: JDKunk@⦠| Owner: anthonyw
Type: Bugs | Status: new
Milestone: To Be Determined | Component: threads
Version: Boost 1.47.0 | Severity: Showstopper
Keywords: |
------------------------------+---------------------------------------------
In boost::thread_group, the join_all function locks mutex m. So in other
functions which use lock_guard, the lock_guard locks mutex m creating
deadlock with multiple modifiers to the thread_group. The solution
includes changing join_all so the mutex is only locked upon obtaining the
next element of the thread_group's thread. Since a std::list is used,
using an iterator while making it possible for another thread to modify
the list is unacceptable. The solutions is to pop the std::list like a
queue. So the front thread is dequeued while the mutex is locked, then the
mutex is unlocked when the thread is joined. Thus it is possible for
multiple threads to modify the thread_group while join_all has occurred.
This code represents the current problem with the join_all function and
other modifiers.
{{{
void join_all()
{
boost::shared_lock<shared_mutex> guard(m);
...
void interrupt_all()
{// This accessor has no problem with join_all
boost::shared_lock<shared_mutex> guard(m);
...
void remove_thread(thread* thrd)
{// This modifier has no problem with join_all
boost::lock_guard<shared_mutex> guard(m);
...
}}}
The below code is my minimal test case for this problem.
{{{
#include <boost/thread.hpp>
boost::mutex lock;
boost::thread * t[128];
boost::thread_group tg;
void run(int i) {
lock.lock();
// remove_thread locks the thread_group's mutex,
// and join_all locks the thread_group's mutex
// causing deadlock.
tg.remove_thread(t[i]); // ***** Deadlock when tg.m is locked.
}
int main() {
lock.lock();
for( int i = 0; i < 128; ++i ) {
t[i] = new boost::thread(run,i);
tg.add_thread(t[i]);
}
lock.unlock();
tg.join_all(); // ***** Deadlock when tg.m is locked.
}
}}}
Finally here is my solution to the given problem.
{{{
void join_all()
{
boost::thread * t;
while( 1 ) {
{
boost::lock_guard<shared_mutex> guard(m);
if( threads.empty() )
break;
t = threads.front();
threads.pop_front();
}
t->join();
}
}
}}}
Thank you, Jeff Kunkel
-- Ticket URL: <https://svn.boost.org/trac/boost/ticket/5432> 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:06 UTC