在2010年对Automatically release mutex on crashes in Unix问题的评论中,jilles声称:
glibc强大的互斥体是如此之快,因为glibc采用了危险的快捷方式。当内核将其标记为“将导致EOWNERDEAD”时,无法保证互斥锁仍然存在。如果互斥锁被破坏并且内存映射文件替换为内存映射文件恰好包含在正确位置的最后一个拥有线程的ID而最后一个拥有线程在写入锁定字之后终止(但在从其列表中完全删除互斥锁之前)拥有的互斥锁),文件已损坏。 Solaris和will-be-FreeBSD9强大的互斥体速度较慢,因为它们不想冒这个风险。
我无法理解索赔,因为除非它被解锁(因此不在任何线程的强健列表中),否则销毁互斥锁是不合法的。我也找不到任何搜索这样的错误/问题的参考资料。索赔是否只是错误的?
我问及我感兴趣的原因是,这与我自己实现的相同Linux robust-mutex原语的正确性有关。
答案 0 :(得分:8)
我想我找到了这场比赛,而且确实非常难看。它是这样的:
线程A拥有强大的互斥锁并解锁它。基本程序是:
问题在于,在步骤3和步骤4之间,同一进程中的另一个线程可以获取互斥锁,然后将其解锁,并且(正确地)相信自己是互斥锁的最终用户,销毁并释放/释放它。之后,如果进程中的任何线程创建了文件,设备或共享内存的共享映射,并且它恰好被分配了相同的地址,并且该位置的值碰巧匹配仍在步骤之间的线程的pid解锁3和4,你有一种情况,如果进程被终止,内核将通过设置它认为是互斥锁所有者id的32位整数的高位来破坏映射文件。
解决方案是在上面的步骤2和4之间对mmap / munmap进行全局锁定,与我对此问题的答案中描述的屏障问题的解决方案完全相同:
Can a correct fail-safe process-shared barrier be implemented on Linux?
答案 1 :(得分:6)
FreeBSD pthread开发人员David Xu对比赛的描述:http://lists.freebsd.org/pipermail/svn-src-user/2010-November/003668.html
我不认为比赛严格要求munmap / mmap周期。共享内存也可能被用于不同的用途。这是不常见但有效的。
正如该消息中所提到的,如果具有不同权限的线程访问常见的健壮互斥锁,则会发生更多“有趣”。由于拥有的健壮互斥体列表的节点位于互斥锁本身中,因此具有低权限的线程可能会损坏高权限线程的列表。这可以很容易地被利用来使高权限线程崩溃,并且在极少数情况下这可能允许高权限线程的内存被破坏。显然,Linux强大的互斥锁仅供具有相同权限的线程使用。通过将强健列表完全放在线程内存中而不是链接列表中,可以轻松避免这种情况。