0

When having multiple threads using shared data, how does one correctly handle the destruction of that data when exceptions are thrown?

I'm working on an application where I want one process to be doing work while waiting for a result sent from another process over a network. I implemented a class that creates a thread to wait for the result, something like the following (actual code is too large to post here, so this is a small example):

class Notifier {
  public: 
    Notifier(Client* _client) : value(-1), client(_client) {
      listener = boost::thread(&Notifer::Listen, this);
    }

    void Listen() {
      try {
        int rec = client->Receive(); //blocking call to receive data over a socket
        boost::scoped_lock sl(mutex);
        value = rec;
      } catch (...) {
        cout << "Exception thrown in listener" << endl;
      }
    }

    int Get() {
      boost::mutex::scoped_lock sl(mutex);
      return value;
    }

  private:
    int value;
    boost::mutex; 
    boost::thread listener;
    Client* client;
}

int main() {
  Client client; //initialize client, connect, etc.
  Notifier n(client);
  while(n.Get() < 0) {
   // do work
   cout << "Waiting for data" << endl;
   sleep(1);
  }
}

This works fine for me until I add exception handling:

int main() {
  try {
    Client client; //initialize client, connect, etc.
    Notifier n(client);
    while(n.Get() < 0) {
     // do work
     cout << "Waiting for data" << endl;
     sleep(1);
     throw exception();
    }
  } catch(...) {
    cout << "Exception thrown in main" << endl;
  }
  return 0;
}

I get the error

"boost: mutex lock failed in pthread_mutex_lock: Invalid argument".

My guess is that, when the exception gets thrown, the stack for the main function gets unwound, destroying the mutex. Then the Receive() call in the Listen function returns and the scoped_lock constructor tries to lock the mutex, which doesn't exist, resulting in the error.

Can someone confirm that this is indeed what is happening? If so, is there a way to communicate to the thread that that the mutex no longer exists or that the thread should terminate? Or is there a more exception-safe way of doing what I'm trying to do?

4

1 回答 1

0

您必须为Notifier类编写一个正确的析构函数,这将取消所有阻塞的调用(即 unblock client->Receive()),然后终止listener线程。您还需要修改Notifier::Listen()以定期检查线程终止请求......然后一切都会好的。

于 2013-07-26T04:03:24.017 回答