(这个问题可能与信号处理程序中的 pthread_exit 导致分段错误有关)我正在编写一个引导锁预防库,其中始终有一个检查线程执行图形操作并检查是否存在死锁,如果是,则它发出信号之一冲突的线程。当该线程捕获信号时,它会释放它拥有的所有互斥体并退出。有多个资源互斥体(显然)和一个临界区互斥体,所有获取、释放资源锁和进行图计算的调用都必须首先获得该锁。现在问题来了。如果有 2 个竞争线程(不包括检查线程),有时程序会在一个线程被杀死后陷入死锁。在 gdb 中,它表示死线程拥有临界区锁,但从未释放它。在信号处理程序中添加断点并单步执行后,似乎锁在 pthread_exit() 之前属于其他人(如预期),但所有权在 pthread_exit() 之后神奇地转到了该线程。
我能想到的唯一猜测是要被杀死的线程在尝试获取关键区域锁时阻塞在 pthread_mutex_lock 处(因为它需要另一个资源互斥锁),然后信号到来,中断 pthread_mutex_lock。由于这个调用没有信号防护,所以发生了奇怪的事情?就像信号处理程序可能已经返回并且该线程获得锁然后退出一样?Idk..任何见解表示赞赏!
pthread_exit不是异步信号安全的,因此从信号处理程序调用它的唯一方法是确保信号不会中断任何非异步信号安全函数。
作为一般原则,使用信号作为与线程通信的方法通常是一个非常糟糕的主意。您最终会混合两个本身就已经足够困难的问题:线程安全(线程之间的正确同步)和单个线程内的重入。
如果您的信号目标只是指示线程终止,那么更好的机制可能是pthread_cancel。然而,为了安全地使用它,将被取消的线程必须在适当的点设置取消处理程序和/或在不安全时暂时禁用取消(使用pthread_setcancelstate)。另请注意,这pthread_mutex_lock不是取消点。没有安全的方法来中断正在等待获取互斥锁的线程,因此,如果您需要这样的可中断性,您可能需要使用条件变量进行更精细的同步设置(condvar 等待是可取消的),或者您可以使用信号量来代替互斥体。
编辑:如果您确实需要一种方法来终止等待互斥体的线程,您可以将调用替换pthread_mutex_lock为对您自己的函数的调用,该函数在每次超时时循环调用pthread_mutex_timedlock并检查退出标志。
| 归档时间: |
|
| 查看次数: |
3287 次 |
| 最近记录: |