【发布时间】:2010-12-16 17:21:03
【问题描述】:
如何在 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();
据我所知,这应该可以工作,而且通常可以,但有时会崩溃。据我从corefile中可以确定,我对问题的猜测是这样的:
- 当回调广播 m_done 结束时,等待线程被唤醒
- 等待线程现在在这里完成,等待被销毁。 Wait 的所有成员都被销毁,包括 mutex 和 cond。
- 回调线程尝试从广播点继续,但现在正在使用已释放的内存,这会导致内存损坏。
- 当回调线程尝试返回时(高于我糟糕的回调方法的级别),程序崩溃(通常使用 SIGSEGV,但我见过几次 SIGILL)。
我尝试了很多不同的机制来尝试解决这个问题,但没有一个能解决问题。我仍然看到偶尔的崩溃。
编辑:更多细节:
这是大规模多线程应用程序的一部分,因此创建静态等待是不切实际的。
我运行了一个测试,在堆上创建 Wait,并故意泄漏内存(即 Wait 对象永远不会被释放),结果没有崩溃。所以我确定这是 Wait 过早释放的问题。
在wait 解锁后,我还尝试使用sleep(5) 进行测试,这也没有产生崩溃。不过,我讨厌依赖这样的组合。
编辑:第三方详细信息:
一开始我不认为这是相关的,但我越想越觉得这是真正的问题:
我提到的第三方的东西,以及为什么我无法控制线程:这是使用 CORBA。
因此,CORBA 持有对我的对象的引用的时间可能比预期的要长。
【问题讨论】:
标签: c++ multithreading pthreads corba