[英]How do I debug a deadlock of readers-writer locks?
我正在编写一个程序,它有一个线程将点文件读入缓冲区,许多线程从缓冲区中获取点并构造它们的八叉树。 八叉树的每个多维数据集都由一个读写锁(又名 shared_mutex)保护,其中有 67 个(如果有两个线程,现在有)。 如果文件太大,程序就会死锁,我很难调试它。 其中一个锁在 gdb 中如下所示:
[6] = {_M_impl = {_M_rwlock = {__data = {__readers = 1,
__writers = 0, __wrphase_futex = 1, __writers_futex = 0, __pad3 = 0,
__pad4 = 0, __cur_writer = 0, __shared = 0, __rwelision = 0 '\000',
__pad1 = "\000\000\000\000\000\000", __pad2 = 0, __flags = 0},
__size = "\001\000\000\000\000\000\000\000\001", '\000' <repeats 46 times>, __align = 1}}},
大多数互斥体的 __readers=1,一个有 __readers=3,一个有 __readers=4294967289 左右。 这是没有意义的,因为只有两个线程,所以只有两个线程可以读取它们; 在构建八叉树阶段,他们应该是写锁定而不是读锁定互斥锁,并且 -7 看起来像七个线程已经读解锁了互斥锁而没有先读锁定它。 尝试在 __readers 上设置观察点不起作用; 它使调试器崩溃,或类似的东西。
我为锁定和解锁写了一个包装器:
void lockBlockR(int block)
{
metaMutex.lock();
modReaders[block%modMutexSize]++;
metaMutex.unlock();
modMutex[block%modMutexSize].lock_shared();
}
void lockBlockW(int block)
{
modMutex[block%modMutexSize].lock();
}
void unlockBlockR(int block)
{
metaMutex.lock();
if (--modReaders[block%modMutexSize]<0)
cout<<"Read-unlocked "<<block<<" too many times\n";
metaMutex.unlock();
modMutex[block%modMutexSize].unlock_shared();
}
void unlockBlockW(int block)
{
modMutex[block%modMutexSize].unlock();
}
当程序挂起时,我查看了 modReaders 并且全为零,然后查看 modMutex 并且它再次具有大部分 __readers=1 和一个负数。 我如何弄清楚发生了什么?
我正在运行 Eoan Ermine、Linux 5.3.0 和 libc 2.30。 该程序使用C++17中的gcc 9.2.1编译。
我以前在 PerfectTIN ( https://github.com/phma/perfecttin ) 中使用了读写器锁和模锁池,但是模池中的锁是普通的互斥锁。
ETA:我添加了另一个名为 modWriters 的整数modWriters
和一些调试语句,并在解锁未锁定的互斥锁时捕获了一个线程。 但是,它是写锁定和写解锁,所以这并不能解释为什么__readers
搞砸了。
如何调试读写锁死锁?
Consider using valgrind , GCC 10static analysis options, andinstrumentation options such as -fsanitize=thread
, and Clang static analyzer .
从它的源代码构建GCC 10是值得的。
请注意,并非总是可以静态可靠地检测所有死锁(赖斯定理)。 阅读这份报告草稿。 你可以有heisenbugs 。
可能使用 C++线程库,特别是std::lock_guard
你可能更喜欢std::recursive_mutex
到std::mutex
,即使递归互斥体更慢更重(有些人说应该避免)。 我的观点是,它们通常更安全。
请注意futex(7) ,Linux 上的基本锁定块。 您可以使用strace(1) (和pipe(7)进行线程间通信或与poll(2)同步;另请参见eventfd(2) )
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.