从线程内分叉是否安全? [英] Is it safe to fork from within a thread?

查看:27
本文介绍了从线程内分叉是否安全?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Let me explain: I have already been developing an application on Linux which forks and execs an external binary and waits for it to finish. Results are communicated by shm files that are unique to the fork + process. The entire code is encapsulated within a class.

现在我正在考虑线程化进程以加快速度.拥有许多不同的类函数实例,同时派生并执行二进制文件(使用不同的参数),并将结果与​​它们自己独特的 shm 文件进行通信.

Now I am considering threading the process in order to speed things up. Having many different instances of class functions fork and execute the binary concurrently (with different parameters) and communicate results with their own unique shm files.

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

Is this thread safe? If I fork within a thread, apart from being safe, is there something I have to watch for? Any advice or help is much appreciated!

推荐答案

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

The problem is that fork() only copies the calling thread, and any mutexes held in child threads will be forever locked in the forked child. The pthread solution was the pthread_atfork() handlers. The idea was you can register 3 handlers: one prefork, one parent handler, and one child handler. When fork() happens prefork is called prior to fork and is expected to obtain all application mutexes. Both parent and child must release all mutexes in parent and child processes respectively.

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

This isn't the end of the story though! Libraries call pthread_atfork to register handlers for library specific mutexes, for example Libc does this. This is a good thing: the application can't possibly know about the mutexes held by 3rd party libraries, so each library must call pthread_atfork to ensure it's own mutexes are cleaned up in the event of a fork().

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

The problem is that the order that pthread_atfork handlers are called for unrelated libraries is undefined (it depends on the order that the libraries are loaded by the program). So this means that technically a deadlock can happen inside of a prefork handler because of a race condition.

例如,考虑这个序列:

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

这是您的死锁,它与您自己的互斥锁或代码无关.

There's your deadlock and its unrelated to your own mutexes or code.

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

This actually happened on a project I once worked on. The advice I had found at that time was to choose fork or threads but not both. But for some applications that's probably not practical.

这篇关于从线程内分叉是否安全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆