【发布时间】:2012-07-11 15:47:53
【问题描述】:
在我对pthread_join() 的调用中,当我的应用程序正在关闭时,我在 C++ 中获得了一个无法轻易重现的 SEGV(它发生在大约 100,000 次测试运行中)。我检查了 errno 的值,它是零。这是在 Centos v4 上运行的。
pthread_join() 在什么条件下会获得 SEGV?这可能是某种竞争条件,因为它极为罕见。有人建议我不应该调用 pthread_detach() 和 pthread_exit(),但我不清楚为什么。
我的第一个工作假设是 pthread_join() 正在被调用,而 pthread_exit() 仍在另一个线程中运行,这会导致 SEGV,但许多人表示这不是问题。
在应用程序退出期间在主线程中获取 SEGV 的失败代码大致如下(为简洁起见省略了错误返回代码检查):
// During application startup, this function is called to create the child thread:
return_val = pthread_create(&_threadId, &attr,
(void *(*)(void *))initialize,
(void *)this);
// Apparently this next line is the issue:
return_val = pthread_detach(_threadId);
// Later during exit the following code is executed in the main thread:
// This main thread waits for the child thread exit request to finish:
// Release condition so child thread will exit:
releaseCond(mtx(), startCond(), &startCount);
// Wait until the child thread is done exiting so we don't delete memory it is
// using while it is shutting down.
waitOnCond(mtx(), endCond(), &endCount, 0);
// The above wait completes at the point that the child thread is about
// to call pthread_exit().
// It is unspecified whether a thread that has exited but remains unjoined
// counts against {PTHREAD_THREADS_MAX}, hence we must do pthread_join() to
// avoid possibly leaking the threads we destroy.
pthread_join(_threadId, NULL); // SEGV in here!!!
退出时加入的子线程运行以下代码,该代码从上面在主线程中调用releaseCond()的点开始:
// Wait for main thread to tell us to exit:
waitOnCond(mtx(), startCond(), &startCount);
// Tell the main thread we are done so it will do pthread_join():
releaseCond(mtx(), endCond(), &endCount);
// At this point the main thread could call pthread_join() while we
// call pthread_exit().
pthread_exit(NULL);
线程似乎正常启动,在应用程序启动期间创建过程中没有产生错误代码,线程正确执行了它的任务,大约在应用程序退出前大约五秒钟。
什么可能导致这种罕见的 SEGV 发生,以及我应该如何针对它进行防御性编程。一种说法是我对 pthread_detach() 的调用是问题所在,如果是这样,我的代码应该如何更正。
【问题讨论】:
-
您是否检查了本地文档以了解您的 pthread_join() 并非所有都符合标准,您可能必须传递一个非 NULL 指针。
-
“子线程”如何知道何时调用该退出代码?该退出代码是如何被调用的?
-
Centos 4?很复古。 LinuxThreads 还是 NPTL?
-
@Loki man pthread_join 允许空指针。
-
@user315052 子线程知道因为主线程将状态变量设置为退出,然后释放启动条件,所以子线程将检查状态变量以查看请求的操作。为简洁起见,我省略了这一点。退出代码由从主线程管理子线程的对象的析构函数调用。
标签: c++ pthreads centos race-condition segmentation-fault