What happens when a destructor of a thread object is called that expects a condition variable?

I use SynchronisedQueue to communicate between threads. I found that destroying a thread object when an attaching thread expects a condition variable will cause the program to crash. This can be fixed by calling detach() before destroying the stream. But I wonder what happens when a thread waiting for a conditional variable ends. Is there any other way to use a condition variable to avoid this?

 #include <queue> #include <thread> #include <mutex> #include <condition_variable> template <typename Type> class SynchronisedQueue { public: void Enqueue(Type const & data) { std::unique_lock<std::mutex> lock(mutex_); queue_.push(data); condition_.notify_one(); } Type Dequeue() { std::unique_lock<std::mutex> lock(mutex_); while (queue_.empty()) condition_.wait(lock); Type result = queue_.front(); queue_.pop(); return result; } private: std::queue<Type> queue_; std::mutex mutex_; std::condition_variable condition_; }; class Worker { public: Worker(SynchronisedQueue<int> * queue) : queue_(queue) {} void operator()() { queue_->Dequeue(); // <-- The thread waits here. } private: SynchronisedQueue<int> * queue_; }; int main() { auto queue = new SynchronisedQueue<int>(); Worker worker(queue); std::thread worker_thread(worker); worker_thread.~thread(); // <-- Crashes the program. return 0; } 
+7
source share
3 answers

From the C ++ 11 spec:

30.3.1.3 thread destructor [thread.thread.destr] ~ thread ();

If joinable (), calls std :: terminate (). Otherwise, it has no effect.

[Note. Either the implicit splitting or merging of a joinable () stream in its destructor can lead to debugging errors (for detachment) or performance (for merging) that occur only when an exception occurs. Thus, the programmer must ensure that the destructor will never execute while the thread is still connecting. - final note]

Thus, calling thread destructor without first calling join (to wait for completion) or detach was guaranteed to immediately call std::terminate and terminate the program.

+11
source

You cannot, ever, destroy a resource while something is or can be using it. It really is just common sense.

+1
source

The destructor for std::thread will call std::terminate if it is running on the thread, if you did not call join() (to wait for the thread to finish) or detach() (to disconnect the thread from the object) on it.

Your code calls the destructor for worker_thread without calling join() or detach() on it, and so std::terminate called. This is not due to the presence of condition variables.

+1
source

All Articles