从multithreading应用程序生成进程

我有一种情况,我需要从一个非常大的multithreading应用程序中产生一个辅助进程,但是我没有完全的控制权。

现在我正在使用fork() / exec() 。 这在很多情况下都是有效的,但是在某些情况下,在exec()发生之前,孩子会奇怪地崩溃。 我怀疑这是因为fork()multithreading应用程序通常被认为是一个真正的坏主意。

我真的很喜欢以primefaces方式启动一个进程的方式,没有fork()父进程:所有文件描述符closures,环境设置我想要的方式,CWD设置等。这应该避免所有的fork()我的multithreading父应用程序,并处理文件描述符inheritance,等posix_spawn()应该是理想的。 不幸的是,在Linux上, posix_spawn()使用fork()exec()

vfork()被定义为挂起父进程,直到subprocess调用exec() 。 这似乎更像我想要的,但我的理解是, vfork()通常被认为是一个历史遗迹这些天,相当于fork() —这仍然是这种情况?

处理这个问题最糟糕的方式是什么?

注意:

  • 我不能在任何线程启动之前产生我的进程(因为我不能在那个时候运行代码)
  • 由于外部的要求,我不能重新devise我的应用程序不需要帮助程序
  • 在产卵辅助过程之前,我不能暂停所有的线程,因为它们不属于我

这是在Linux上。 涉及Java,但所有的代码都在C

Solutions Collecting From Web of "从multithreading应用程序生成进程"

如果将自己限制为“原始”系统调用( syscall(SYS_fork)syscalll(SYS_execve, ...)等) syscalll(SYS_execve, ...)调用fork应该是安全的。 调用任何glibc例程,你会遇到很多麻烦。

调用vfork完全不是你想要的:只有被称为vfork的线程被挂起,其他线程将继续运行(和vforked子进程在同一个地址空间中)。 这很可能使你的生活复杂化。

直接调用clone是可能的,但是非常棘手。 我们有一个允许从多线程应用程序中安全分派子进程的实现(不幸的是不是开源的)。 这个代码非常复杂,而且非常长。

如果仅使用异步信号安全操作,则fork'ing多线程应用程序被认为是安全的。 POSIX 说 :

一个进程应该创建一个单一的线程。 如果多线程进程调用fork(),则新进程将包含调用线程的副本及其整个地址空间,可能包括互斥锁和其他资源的状态。 因此,为了避免错误,子进程可能只执行异步信号安全操作,直到调用其中一个exec函数为止。 分叉处理程序可以通过pthread_atfork()函数建立,以便在fork()调用中维护应用程序不变量。

posix_spawn()不是最好的主意:

临时修改多线程进程的环境也很复杂,因为所有线程都必须同意何时可以改变环境的安全性。 但是,这些成本只能由那些使用附加功能的posix_spawn()和posix_spawnp()调用来承担。 由于大量的修改不是通常的情况,而且对时间要求严格的代码来说尤其不可能,因此保持posix_spawn()和posix_spawnp()的大部分环境控制是合适的设计。

(看man posix_spawn )

我想你有从父资源复制的问题。 你可以使用pthread_atfork()处理程序清理它们(你使用pthread,对吧?)。 另一种方法是使用低级函数来创建名为clone()的进程。 它几乎可以完全控制子进程应该从父进程继承什么。

[UPDATE]

解决这个问题的最简单方法可能就是改变你的分拣方案。 例如,即使在程序初始化所有资源之前,您也可以创建一个新的进程(fork)。 即在创建所有线程之前,在main()中调用fork()。 在子进程中设置一个信号处理程序(例如SIGUSR2信号)和睡眠。 当父母需要执行某个新的进程时,它会将SIGUSR2信号发送给您的子进程。 当孩子抓住它时,它调用fork / exec。