如何在C++中等待已分离的线程完成?
我不关心退出状态,我只想知道线程是否已完成。
我试图为异步第三方工具提供同步包装器。 问题是涉及回调的奇怪竞争条件崩溃。 进展如下:
- 我调用第三方并注册回调
- 当第三方完成时,它使用回调通知我--在一个我无法真正控制的分离线程中。
- 我希望来自(1)的线程等待直到调用(2)。
我想将其包装在提供阻塞调用的机制中。 到目前为止,我有:
class Wait {
public:
void callback() {
pthread_mutex_lock(&m_mutex);
m_done = true;
pthread_cond_broadcast(&m_cond);
pthread_mutex_unlock(&m_mutex);
}
void wait() {
pthread_mutex_lock(&m_mutex);
while (!m_done) {
pthread_cond_wait(&m_cond, &m_mutex);
}
pthread_mutex_unlock(&m_mutex);
}
private:
pthread_mutex_t m_mutex;
pthread_cond_t m_cond;
bool m_done;
};
// elsewhere...
Wait waiter;
thirdparty_utility(&waiter);
waiter.wait();
据我所知,这应该可以工作,并且通常也能工作,但有时会崩溃。从核心文件中可以确定问题是这样的:
- 当回调广播 m_done 的结束时,等待线程会被唤醒
- 等待线程现在已经完成,Wait 被销毁。Wait 的所有成员都被销毁,包括互斥锁和条件变量。
- 回调线程尝试从广播点继续执行,但现在正在使用已释放的内存,导致内存损坏。
- 当回调线程尝试返回(在我的糟糕回调方法的上面)时,程序会崩溃(通常是 SIGSEGV,但我几次看到过 SIGILL)。
编辑:更多细节:
这是一个大规模多线程应用程序的一部分,因此创建静态 Wait 并不实际。
我运行了一个测试,在堆上创建 Wait,并故意泄漏内存(即 Wait 对象从未被释放),结果没有崩溃。所以我确定这是 Wait 被释放得太早的问题。
我还尝试了在 wait 中解锁后使用 sleep(5) 的测试,也没有出现崩溃。虽然我不喜欢依赖这样的 hack。
编辑:第三方细节:
一开始我认为这与问题无关,但越想越觉得这是真正的问题:
我提到的第三方东西,以及为什么我无法控制线程:这是使用 CORBA。
因此,CORBA 可能会比预期更长时间地保留对我的对象的引用。