The worker threads in a ThreadPool don't signal the pool's condition variable when completing the last task in the queue. As a consequence, ThreadPool::join() hangs if called while the task queue is non-empty.