c++ - 从线程内 fork 是否安全?

让我解释一下:我已经在 Linux 上开发了一个应用程序,它 fork 并执行一个外部二进制文件并等待它完成。结果由 fork + 进程独有的 shm 文件传达。整个代码封装在一个类中。

现在我正在考虑对流程进行线程化以加快速度。有许多不同的类函数实例同时派生和执行二进制文件(使用不同的参数),并使用它们自己独特的 shm 文件来传达结果。

这个线程安全吗?如果我在一个线程中 fork ,除了安全之外,还有什么需要注意的吗?非常感谢任何建议或帮助!

最佳答案

问题是 fork() 只复制调用线程,并且子线程中持有的任何互斥锁将永远锁定在 fork 的子线程中。 pthread 解决方案是 pthread_atfork() 处理程序。这个想法是您可以注册 3 个处理程序:一个 prefork、一个父处理程序和一个子处理程序。当 fork() 发生时 prefork 在 fork 之前被调用,并且预期会获得所有应用程序互斥体。父进程和子进程都必须分别释放父进程和子进程中的所有互斥锁。

这不是故事的结局!库调用 pthread_atfork 来为库特定的互斥锁注册处理程序,例如 Libc 就是这样做的。这是一件好事:应用程序不可能知道第三方库持有的互斥锁,因此每个库都必须调用 pthread_atfork 以确保在发生 fork()

问题在于不相关的库调用 pthread_atfork 处理程序的顺序是未定义的(这取决于程序加载库的顺序)。所以这意味着从技术上讲,由于竞争条件,prefork 处理程序内部可能会发生死锁。

例如,考虑这个序列:

  1. 线程 T1 调用 fork()
  2. 在 T1 中调用 libc prefork 处理程序(例如,T1 现在拥有所有 libc 锁)
  3. 接下来,在线程 T2 中,第 3 方库 A 获取其自己的互斥体 AM,然后进行需要互斥体的 libc 调用。这会阻塞,因为 libc 互斥锁由 T1 持有。
  4. 线程 T1 为库 A 运行 prefork 处理程序,该处理程序阻塞等待获取由 T2 持有的 AM。

您的死锁与您自己的互斥锁或代码无关。

这实际上发生在我曾经参与的一个项目中。我当时找到的建议是选择 fork 或 threads,但不能同时选择两者。但是对于一些可能不实用的应用程序。

https://stackoverflow.com/questions/6078712/

相关文章:

linux - 如何检测文本文件中的无效 utf8 unicode/binary

c - 在 Linux 中何时使用 pthread_exit() 以及何时使用 pthread_jo

linux - 如何使用 bash 在文件中间添加一行文本?

c - 为什么 pthread 互斥锁被认为是 "slower"而不是 futex?

linux - 一个进程如何拦截Linux上另一个进程的stdout和stderr?

c - 如何优雅地退出 X11 事件循环?

c++ - 如何在不重新打印的情况下更新终端中的打印消息

linux - "zero copy networking"与 "kernel bypass"?

linux - 查找和基本名称不能很好地播放

linux - 为什么 Linux 不通过 TSS 使用硬件上下文切换?