1

(这个问题可能与信号处理程序中的 pthread_exit 导致分段错误有些相关)我正在编写一个铅锁预防库,其中总是有一个检查线程在做图形工作并检查是否存在死锁,如果是,那么它发出信号之一冲突的线程。当该线程捕获到信号时,它会释放它拥有的所有互斥体并退出。有多个资源互斥锁(显然)和一个临界区互斥锁,所有获取、释放资源锁和进行图计算的调用都必须先获取此锁。现在问题出现了。有 2 个竞争(不包括检查线程)线程,有时一个线程被杀死后程序死锁。在 gdb 中,它说死线程拥有关键区域锁但从未释放它。在信号处理程序中添加断点并逐步执行后,似乎锁在 pthread_exit() 之前属于其他人(如预期的那样),但所有权在 pthread_exit() 之后神奇地转到了这个线程。

我能想到的唯一猜测当试图获得临界区锁(因为它想要另一个资源互斥锁)时,要被杀死的线程是否在 pthread_mutex_lock 处阻塞,然后信号来了,中断了 pthread_mutex_lock。由于这个调用不是信号证明的,所以发生了一些奇怪的事情?就像信号处理程序可能已经返回并且该线程获得锁然后退出一样?Idk ..任何见解表示赞赏!

4

1 回答 1

3

pthread_exit不是异步信号安全的,因此您可以从信号处理程序调用它的唯一方法是确保信号不会中断任何非异步信号安全功能。

作为一般原则,使用信号作为与线程通信的方法通常是一个非常糟糕的主意。您最终会混合两个本身已经足够困难的问题:线程安全(线程之间的正确同步)和单个线程内的可重入性。

如果您使用信号的目标只是指示线程终止,那么更好的机制可能是pthread_cancel. 然而,为了安全地使用它,将被取消的线程必须在适当的点设置取消处理程序和/或在不安全时暂时禁用取消(使用pthread_setcancelstate)。另外,请注意,这pthread_mutex_lock不是取消点。没有安全的方法来中断被阻塞等待获取互斥锁的线程,因此如果您需要像这样的可中断性,您可能需要使用条件变量进行更精细的同步设置(condvar 等待是可取消的),或者您可以使用信号量而不是互斥体。

编辑:如果您确实需要一种方法来终止等待互斥锁的线程,您可以将调用替换为pthread_mutex_lock对您自己的函数的调用,该函数循环调用pthread_mutex_timedlock并在每次超时时检查退出标志。

于 2012-12-03T17:22:59.747 回答