pthread_mutex_lock锁定,但未设置所有者

5

我已经花了几天时间在这个问题上 -

背景是,我正在尝试将一个单线程的C程序改为多线程。最近我发现了一种新的死锁情况,但是当我在gdb中查看互斥锁时,我发现

__lock=2 但 __owner=0

这不是递归互斥锁。有人见过这种情况吗?我正在处理的程序是一个守护进程,在高吞吐量运行20分钟(左右)后才会出现这种情况。如果你有任何想法,我将不胜感激。

编辑 - 我忘记提到此时我的其他所有线程都处于空闲状态。

谢谢


一些源代码,任何源代码以建立上下文会非常有帮助。 - Josh
@nos 我经常在valgrind中运行它以检查是否正常,但我会再多做一些以查看是否犯了新错误。 - dbeer
@Josh - 总体代码超过 200k 行。守护程序通过将定时任务放置在队列中并定期检查是否准备好执行来跟踪定时任务,因此只有在检查对象是否准备好执行时才会查看该对象及其互斥锁。如果准备就绪,则从队列中删除它并调用函数。除此之外,只有在插入其他对象以进行排序时才访问它以检查其时间。 - dbeer
如果您的互斥锁没有正确初始化,您可能会得到这样的结果。 - nos
@dbeer 我使用了一个错误检查的互斥锁,但每次启动时都立即出现相同的问题。没有用户,没有计数,没有所有者,但却发生死锁。锁只会在单个位置上锁定,并在单个位置上解锁,没有办法让它保持锁定。__lock=2,__count=0,__owner=0,__nusers=0,__kind=2,__spins=0 - rutgersmike
显示剩余2条评论
3个回答

5
这是可以预料的。一个正常的(非递归,非错误检查)互斥锁没有必要存储其所有者,并且跳过查找调用者线程ID的步骤可以节省一些时间。(在x86上几乎没有区别,但在像MIPS这样存在破损ABI的平台上可能会产生巨大差异,因为没有线程寄存器且获取线程ID会导致故障进入内核空间。)
您看到的死锁几乎肯定是由线程尝试锁定已经持有的互斥锁,或者实际逻辑错误导致两个或多个线程各自等待其它线程持有的互斥锁所致。

我必须不同意 - 这不是正常的。我过去追踪死锁的方法是检查谁拥有互斥锁,然后进行检查。我应该提到的一个额外细节是,在这一点上,所有其他线程都处于空闲状态(我将编辑我的帖子)。另外,非递归互斥锁如何具有2个锁?我的理解是只有递归互斥锁才能具有> 1的锁值。 - dbeer
@dbeer:R.. 其实是对的,普通互斥锁不保存所有者。如果我没记错的话,递归互斥锁和错误检查互斥锁会保存所有者。 - ninjalj
我将尝试将其变为递归互斥锁并查看结果。 - dbeer
glibc源代码建议在__pthread_mutex_lock函数中获取锁后,所有类型的互斥锁都会保存所有者,nptl/pthread_mutex_lock.c。 - nos
1
嗯,我认为它可以帮助进行诊断/调试,因此并不是完全没有用处。 - nos
显示剩余3条评论

1
我刚刚解决了我遇到的问题 - 栈破坏导致mutex.__data.__lock值在尝试pthread_mutex_lock调用之前被设置为一些荒谬的数字(大约40亿)。请尝试在执行锁操作之前设置断点或打印有关__lock值的调试信息,我愿意打赌,在死锁发生之前,它是无效的。

1
据我所知,这是由于pthread库的限制。每当我发现代码中有过多的锁定和解锁,并且对该代码部分进行了重度压力测试时,就会出现这种故障。我通过重新编写这些部分以最小化它们的锁定来解决这些问题,这样更容易维护代码(重新获取可能已释放对象时减少错误检查),并消除一些开销。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接