首先非常感谢老丁和老李同学的帮助,没有他们这个问题估计又得搞很久。遇见这个问题,真是头疼。不熟悉代码、不熟悉流程,但是领导还是把活给排下来了(实在不解),只能硬着头皮找了。
问题是这样的,cache服务器中有一个存储对象的哈希表,每次访问哈希表时都要获取hash_rwlock读写锁,现在进程在获取读锁时死锁。使用gdb进入3个worker进程,发现死锁的位置都一样,都是在获取hash_rwlock读锁时阻塞住了。遇见这样的问题,加上对代码不熟,真是各种犯二。因为reload的关系,进程其实总共有9个,但是3个是一组的,所以只看了其中的一组,没有全部查看,如果全部查看的话,估计可以更早发现问题。
在同事的提醒下,先在阻塞的位置打印锁的结构,如下所示:
找了glibc的源码来看,发现pthread_rwlock_t结构的成员竟然完全没有注释,只好去看加锁、解锁的函数。在获取读锁时,只有在__writer成员为0并且__nr_writers_queued为0,即没有进程获取写锁或等待获取写锁时,才会获取锁成功。获取读锁成功后,会将__nr_readers成员加1.这么看来的话,__nr_readers存储的是当前获取读锁的进程或线程数量。在获取写锁时,只有在__writer成员为0,并且__nr_readers为0,即没有进程或线程获取写锁或读锁时,才会获取写锁成功。获取写锁成功后,会将__writer成员设置为线程ID(如果是单进程,则为进程ID),如下所示:
rwlock->__data.__

本文讲述了作者在遇到缓存服务器中由于获取哈希表读写锁导致的死锁问题,通过分析glibc源码,打印锁结构信息,最终定位到进程在获取读锁和写锁时的冲突。通过gdb调试发现,两个进程分别持有不同锁并尝试获取对方持有的锁,导致死锁。问题源于某函数在失败时不正确释放锁。
最低0.47元/天 解锁文章
1387

被折叠的 条评论
为什么被折叠?



