Boost logo

Boost Users :

From: Scott Gifford (sgifford_at_[hidden])
Date: 2007-10-03 19:47:57


Hello,

I'm writing a multithreaded server on Unix using boost::thread. The
basic operation is fairly straightforward; a master thread starts up
worker threads, and coordinates various management tasks using
condition variables.

As with most Unix servers, the server is shut down with an OS signal
telling the server to shut down. The server catches this signal, then
simply calls exit(1). Any important cleanup happens in the
destructors of global variables, so it will happen properly no matter
how the server exits.

One object which is always cleaned up is the object for the master
thread. The master thread sets a flag, then does a notify_all() on
some condition variables to tell the other threads to shut down,

The problem I'm having is that if the master thread is waiting on a
condition variable when the signal arrives, and the destructor does a
notify_all() on that condition variable, then the destructor for the
boost::condition variable hangs.

For example, if I run the included code and hit CTRL-C after a short
bit, I get this output:

    Waiting...
    ^C
    Caught signal 2
    Destroyed ThreadTest
    Running destructor 1
    [ ... hangs ... ]

Here is the program:

    #include <iostream>
    #include <signal.h>
    #include <boost/thread.hpp>
    #include <boost/thread/mutex.hpp>
    #include <boost/thread/condition.hpp>
    
    
    template<int n>
    struct PrintOnDestruct {
      ~PrintOnDestruct() {
        std::cout << "Running destructor " << n<< std::endl;
      }
    };
    
    class ThreadTest {
      public:
        void doSomething() {
          boost::mutex::scoped_lock lock(myMutex);
          while(true) {
            std::cout << "Waiting..." << std::endl;
            myCond.wait(lock);
          }
        }
        ~ThreadTest() {
          boost::mutex::scoped_lock lock(myMutex);
          myCond.notify_all();
          std::cout << "Destroyed ThreadTest" << std::endl;
        }
      private:
        PrintOnDestruct<2> d2;
        boost::mutex myMutex;
        boost::condition myCond;
        PrintOnDestruct<1> d1;
    };
    
    // Exit properly on signal
    void sighandle(int sig) {
      std::cerr << "Caught signal " << sig << std::endl;
      exit(1);
    }
    
    ThreadTest tt;
    
    int main() {
      // Get ready to handle signals
      signal(SIGINT,sighandle);
    
      tt.doSomething();
    }

Does anybody have any suggestions for a straightforward way to handle
this properly?

Thanks!

----ScottG.


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