pthread_cond_wait:随机分段错误
pthread_cond_wait: random segmentation fault
更新3
最近,我注意到我的代码随机导致分段错误错误。但我认为到目前为止我的代码非常简单,我不知道错误是从哪里来的。由于它是随机发生的,我认为存在某种种族条件。我认为这是所有可能相关的代码,如果你需要更多,请告诉我:
namespace thread {
pthread_t terminated_thread_id, /* and others */;
pthread_mutex_t terminate_thread = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t terminate_thread_signal = PTHREAD_COND_INITIALIZER;
int total_thread_count = 0;
int termination; // + sembufs
inline void* Exit(void* value) {
// This must be unlocked after all join-related jobs are done
semop(thread::termination, thread::termination_in_process, 2)
pthread_mutex_lock(&thread::terminate_thread);
thread::terminated_thread_id = pthread_self();
pthread_cond_signal(&thread::terminate_thread_signal);
pthread_mutex_unlock(&thread::terminate_thread);
pthread_exit(value);
return value;
}
}
int main(int argc, const char** argv){
...
pthread_mutex_lock(&thread::terminate_thread);
if(0 != pthread_create(&thread::communication_handler_thread_id, NULL,
CommunicationHandler, NULL)){
global::PrintDebug("pthread_create() failed", __FILE__, __LINE__);
}
/** 2 more pthread_create()-calls */
do{
thread::terminated_thread_id = pthread_self();
pthread_cond_wait(&thread::terminate_thread_signal,
&thread::terminate_thread);
if(!pthread_equal(thread::terminated_thread_id, pthread_self())){
pthread_join(thread::terminated_thread_id, NULL);
...
semop(thread::termination, thread::termination_done, 1)
}
}while(thread::total_thread_count > 0);
pthread_mutex_unlock(&thread::terminate_thread);
return 0;
}
信号terminate_thread_signal仅在thread::Exit()函数中发出。该函数也仅在用于创建线程的函数结束时调用。
这是调试器为调用堆栈显示的内容:
#0 ( 0xb7fe2424 in __kernel_vsyscall() (??:??)
#1 0xb7fbdfcf __pthread_cond_wait(cond=0x80539c0, mutex=0x8053998) (pthread_cond_wait.c:153)
#2 0x804a094 main(argc=1, argv=0xbffff9c4) (/home/papergay/SeekYourCar/0.2/Server/main.cpp:121)
我已经知道,如果发生错误,那么还没有线程调用thread::Exit()。我还使用了一个未命名的名称空间,并进行了一些初始化(如果这可能相关的话)。我使用Code::Blocks作为IDE,使用GCC作为编译器。
pthread_cond_wait()
被允许虚假唤醒,因此您必须在每次唤醒后重新测试条件本身。这可能会导致您的问题——如果主线程在设置thread::terminated_thread_id
之前错误地唤醒,它将向pthread_join()
传递一个无效的线程id。
代码中还有另一个问题-不能保证发出信号的线程在互斥锁解锁后会是下一个唤醒的线程,因此两个线程可以快速连续调用thread::Exit()
,而主线程直到第二个退出的线程解锁互斥锁后才运行。在这种情况下,您永远不会在第一个线程上调用pthread_join()
。
这样的东西应该可以解决这些问题:
namespace thread {
int terminate_thread_set = 0;
pthread_mutex_t terminate_thread = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t terminate_thread_set_cond = PTHREAD_COND_INITIALIZER;
pthread_cond_t terminate_thread_unset_cond = PTHREAD_COND_INITIALIZER;
/* ... */
inline void Exit(void* value)
{
pthread_mutex_lock(&thread::terminate_thread);
while (thread::terminate_thread_set)
pthread_cond_wait(&thread::terminate_thread_unset_cond);
thread::terminated_thread_id = pthread_self();
thread::terminate_thread_set = 1;
pthread_cond_signal(&thread::terminate_thread_set_cond);
pthread_mutex_unlock(&thread::terminate_thread);
pthread_exit(value);
}
}
在main
:中
pthread_mutex_lock(&thread::terminate_thread);
/* ... */
while(thread::total_thread_count > 0) {
while (!thread::terminate_thread_set)
pthread_cond_wait(&thread::terminate_thread_set_cond, &thread::terminate_thread);
thread::terminate_thread_set = 0;
pthread_join(thread::terminated_thread_id, NULL);
pthread_cond_signal(&thread::terminate_thread_unset_cond);
...
}
pthread_mutex_unlock(&thread::terminate_thread);
当然,这并不是说你没有其他问题。
看起来就像是在从主进程解锁termination_in_process
互斥锁——即使它被另一个线程锁定了——这是未定义的行为。它可能起作用,也可能不起作用。
一个解决方案可以是使用FIFO缓冲区(例如std::队列,甚至只是std::向量),并在Exit()
函数中将终止线程的线程id推送到它,然后发送信号,让主线程通过缓冲区并加入其中的任何线程。
如果在segfault时没有调用Exit()
,这不应该是问题的原因,但这仍然是您可能想要解决的问题。
这已经很晚了,但我忘了发布它以备将来参考。我就是这样修复的:
我将GCC编译器从4.5.X版本升级到4.7.X版本,将内核从2.6.X版本升级到3.2.X版本,并通过提供显式构造函数来修复与类和静态成员变量的全局初始化有关的一些错误,以便在不初始化的情况下进行全局声明。但我认为升级GCC编译器是所有需要的。
看起来函数的实现不正确。或者内核代码中有一些错误?
- 在某些循环内使用vector.push_back时出现分段错误
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 当我的阵列太大时出现分段错误
- 分段错误当我试图运行程序时出错
- 在c++中初始化矩阵时出现分段错误(核心转储)
- 尝试使用集合函数时出现分段错误
- 我无法缩小此分段错误的原因
- g++的分段错误(在NaN上使用to_string两次时)
- 我是如何在这段代码中出现分段错误的
- 创建结构的数组时遇到分段错误
- 在c++中键入向量中的所有值后,得到分段错误(核心转储)
- 在 c++ 中实现 Trie 时出现分段错误
- 为什么 fstream 在打开带有格式的文件时会导致分段错误?
- 为什么我遇到分段错误?
- 动态类的分段错误(家庭作业问题)
- 分段错误 - 读取初始化指针的数组
- 如何摆脱C ++中的分段错误错误?
- 使用 CTYPE 时出现分段错误
- 为什么代码给出分段错误?