【发布时间】:2011-12-30 10:13:15
【问题描述】:
我有一种情况,我需要从一个非常大的多线程应用程序中生成一个辅助进程,而我无法完全控制它。
现在我正在使用fork()/exec()。这在很多时候都有效,但在某些情况下,孩子会在exec() 发生之前奇怪地崩溃。我怀疑这是因为fork()ing 多线程应用程序通常被认为是一个非常糟糕的主意。
我真的非常喜欢一种原子启动进程的方法,而不需要fork()父进程:关闭所有文件描述符,按照我想要的方式设置环境,设置 CWD 等。这应该避免所有的恐怖fork()ing 我的多线程父应用程序,以及处理文件描述符继承等。posix_spawn() 应该是理想的。不幸的是,在 Linux 上,posix_spawn() 是使用 fork() 和 exec() 实现的...
vfork() 被定义为暂停父进程,直到子进程调用exec()。这似乎更像我想要的,但我的理解是vfork()现在普遍被认为是历史遗迹,相当于fork()——现在还是这样吗?
处理这个问题最不坏的方法是什么?
注意:
- 我无法在任何线程启动之前生成我的进程(因为此时我无法运行代码)
- 由于外部要求,我无法重新设计我的应用程序以使其不需要辅助进程
- 在生成辅助进程之前,我无法暂停所有线程,因为它们不属于我
这是在 Linux 上。涉及 Java,但所有我的代码都在 C 中。
【问题讨论】:
-
既然您已经在使用线程,为什么不直接启动一个调用
system()并运行您需要的任何东西的新线程? -
在多线程程序中使用 fork() 没有固有问题,除非它对于需要大量内存和繁忙的线程应用程序来说可能效率低下。
-
system() 通过 fork()/exec() 工作!
-
使用 fork() 和线程的最大问题是,当 fork() 发生时,所有其他线程都消失了——无论它们是否处于临界区。并且锁、信号量等的状态在子进程中变为 undefined。因此,如果一个线程在 malloc() 的中间,然后孩子调用 malloc(),就会发生可怕的事情(我认为这发生在我身上)。事实上,我已经重组了一些东西,以便我使用 vfork() 和唯一一个孩子称之为 exec() 的函数,我认为我的崩溃已经停止显现,但我会还是喜欢答案...
-
@DavidGiven:这里迟到了,但我不希望
posix_spawn或system在 @ 之间进行 non-async-signal-safe 调用987654338@和exec;因此它们应该可以安全地在多线程应用程序中使用,除非他们在手册页中明确说明。