繁体   English   中英

从多线程应用程序生成进程

[英]Spawn process from multithreaded application

我有一种情况,我需要从一个非常大的多线程应用程序中生成一个帮助程序进程,我没有完全控制。

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

我真的非常喜欢以原子方式启动进程的方法,没有fork()父进程:关闭所有文件描述符,环境设置我想要的方式,CWD设置等等。这应该避免fork()所有恐怖fork()我的多线程父应用程序,处理文件描述符继承等, posix_spawn()应该是理想的。 不幸的是,在Linux上, posix_spawn()是使用fork()exec() ...

vfork()被定义为挂起父进程,直到子进程调用exec() 这似乎更像我想要的,但我的理解是, vfork()现在通常被认为是历史遗物,相当于fork() ---这仍然是这样吗?

处理这个问题的最不好的方法是什么?

注意:

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

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

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

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

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

调用vfork根本不是你想要的:只有调用vfork的线程被挂起,其他线程将继续运行(和vforked子节点在同一地址空间)。 这很可能会使你的生活变得复杂。

直接调用clone是可能的,但非常棘手。 我们有一个实现,允许从多线程应用程序安全分叉子进程(遗憾的是不是开源)。 该代码非常棘手,并且令人惊讶地长。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM