有一天,我发现了一篇关于pthreads互斥体实现中可能出现的错误的有趣文章,随后进行了讨论:
https://lwn.net/Articles/575460
我目前对pthreads库(以及一般的多线程编程)的了解对我来说太难以理解大部分讨论,但我必须承认这会让我得出一些非常令人不安的结论。这是否意味着当前实现的pthreads互斥体确实存在严重缺陷,因此,Linux内核(毫无疑问,它主要依赖于多线程代码)可能会被来自该漏洞的关键错误所吞噬?我总是假设代码是基本的,低级的和基本的,因为基本的同步原语如互斥量已经过彻底的测试(甚至被证明是正确的)。相反,我们突然发现那里有一个"特殊情况"每个人都没有注意到多年,包括Linus Torvalds在内的任何人都无法确定内核代码中可能出现的频率。 听起来很可怕,不是吗?
无论如何,问题的当前状态和可能的解决方案是什么(文章是从2013年底开始的)?是否更改了互斥锁实现以涵盖省略的特殊情况?或者是否更改了库文档(POSIX标准?)以加强使用互斥锁安全的条件?有没有做过什么?学习pthreads库是否有意义,如果它很可能是腐败和不可靠的?或者我对这个主题的整体理解是错误的,根本没有问题?
答案 0 :(得分:0)
Pthreads是Posix线程,值得了解任何特定实现。 Linux不是唯一的。 Pthreads经过试用和测试,即使在那里也能很好地工作。
如果您仔细阅读该文章,该问题仅在某些情况下出现。你必须让一个线程等待获取锁定,就在锁定持有者唤醒第三个线程同时等待锁定时。此外,它在这里不安全的原因是“旋转”的行为。线程导致第三个线程出现问题,因为如果第三个线程打算使用它,它显然不会释放包含互斥锁的对象是安全的。
事实上,问题在于互斥体实现中的问题并非如此,而在于它的使用方式,尽管如此肯定是一种解决方案,以便以这种方式使用它是安全的。 它似乎是内核社区关注的问题,因为这个问题可以在一个广泛使用的编码模式中表现出来(即重新计算以决定删除某些内容的安全性)。 如果您感兴趣,可以查看内核更改历史记录以查看是否存在内核更改历史记录。
免责声明:我只是熟悉这些问题。更熟悉互斥实现的人和内核可能能够更好地指导你。
答案 1 :(得分:0)
该文章中显示的互斥锁用法对于POSIX和C ++ 11互斥锁是有效的。 Glibc有类似的bug现已修复。
我认为glibc中的每个同步原语在某些方面都有类似的错误。这里有一些(现在全部修复):
我不确定它现在的状态是什么,但很可能至少共享的POSIX primites并不完全符合。
Musl libc尝试提供POSIX原语的正确实现。这就是共享屏障pthread_barrier_wait
与MAP_FIXED
mmap
调用共享全局进程内锁定的原因。而且我不确定这是否解决了所有问题。很高兴知道glibc如何处理这个问题,很可能它不会,所以这可能是一个基本错误"的例子。
您可能需要查看musl作者的个人资料 - Rich Felker - 以及此处的问题列表以查找许多问题。