Boost logo

Boost Users :

Subject: [Boost-users] Race condition with Boost::Thread
From: Rob Yull (ryull_at_[hidden])
Date: 2009-07-29 10:05:46


I've been writing a thread pool class as kind of an experiment with
boost.threads, boost.bind, and boost.function. The code below is the worker
thread, that will eventually pull jobs from a queue, execute them, then look
and see if there is another job in the queue. I think I've got an
interesting race condition. The problem I'm having is when the class goes
out of scope. I'm getting an access violation from the run() member
function (which is function being run by m_Thread). Right now, run() is
just entering and leaving (no actual queue checking). By the time run() is
getting executed, the class is starting to execute the destructor. I
thought that having the join() call in the destructor should allow the
thread to finish before the class data is destroyed. In Visual Studio
2005's debugger, when it is getting to run(), it looks like the object has
already been destroyed (this = 0x7fffffff), so the access violation is
coming from the assignment to the m_Running member variable. If I take out
the assignment, and run the debug, when it is entering run(), the this
pointer is still showing as invalid, but the function completes and ends up
back at the join() in the destructor, where the this pointer in the
destructor is valid again. So as far as the destructor seems to be
conserned, the class hasn't been destroyed yet, but as far as the member
class is, it has been destroyed already.

 

If I do pad some instructions/time before the class goes out of scope, run()
executes just fine (this pointer is valid). I have also tried moving the
creation of m_Thread outside of the constructor to a separate member
function call, but the result is the same.

 

I know debugging multithreaded apps can be difficult. Is there right out
something I'm doing wrong here or making some kind of bad assumpion about
the execution of run()?

 

#include <boost/config.hpp>

#include <boost/thread.hpp>

#include <boost/functional.hpp>

 

class WorkerThread

{

public:

      typedef boost::function<void ()> JobType;

 

      WorkerThread()

      {

            m_Thread = boost::thread(boost::bind(&WorkerThread::run,
boost::ref(this)));

 

            m_Running = true;

      }

 

      ~WorkerThread()

      {

            m_Thread.join();

      }

 

      const bool isRunning() const

      {

            return m_Running;

      }

 

private:

      volatile bool m_Running;

      boost::thread m_Thread;

 

      void run()

      {

            m_Running = false; // Access violation here

      }

 

private:

      WorkerThread(const WorkerThread& rhs);

      WorkerThread& operator = (const WorkerThread& rhs);

};

 

int main()

{

      WorkerThread wt; // new thread should start executing here

 

      return 0;

}

 

-Rob Yull

 



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net