有没有办法自动关闭叉()上的某些手柄?
背景:我有一个大型现有进程(它恰好在 AIX 上,所以基本上是 POSIX 语义),它是一个更大系统的一部分。现有流程设计为连续运行。此过程的一个新要求是处理一种新型的复杂输入流。为了降低风险,我决定分叉/执行一个子进程来执行实际的输入处理,这将现有的主进程与崩溃或因格式错误的输入数据而挂起等问题隔离开来。
子进程从stdin读取数据,处理后写入stdout。我已经设置了所有通信管道,因此我可以将输入数据从主进程传递给子进程,并以其他方式读取输出,这一切都工作正常(非阻塞以避免死锁等)。子进程的生存时间与主进程从外部源接收(有限)输入流的时间一样长。
我的问题是关于管柄本身的。主进程通过在附加到子进程 stdin 的管道上调用 close()
来通知子进程输入流已完成。只要主进程持有该管道写入端的唯一句柄,此操作就有效。如果主进程由于其他一些不相关的原因决定分叉怎么办?然后,这将为管道的写入端创建两个句柄,这意味着当我尝试关闭标准输入管道的写入端时,子级不会注意到,因为还有另一个写入端句柄结束开放。另一个打开的手柄是我无法控制的。
我知道可以在文件描述符上设置 FD_CLOEXEC 位,以便在 exec() 完成时自动关闭它。但是,这并不能防止主进程分叉但不执行的情况。
这个问题的一般解决方案是什么?我只能想到几个想法:
- 确保(通过检查)现有进程不会在不执行 exec 的情况下任意分叉。这也许是可能的,但不是通用的解决方案。
- 在启动时,分叉一个长期存在的帮助程序进程,其唯一职责是定期分叉/执行执行实际处理的子进程。这样助手的句柄上下文是已知的并且可以很好地控制。然而,这很烦人,因为助手需要某种方式来知道输入流已经结束,而不是关闭它的标准输入。
Background: I've got a large existing process (it happens to be on AIX, so basically POSIX semantics) that's part of an even larger system. The existing processes are designed to run continuously. A new requirement for this process is to handle a new kind of complex input stream. In order to reduce risk, I've decided to fork/exec a child process to do the actual input processing, which isolates the existing main process from problems such as crashes or hangs on malformed input data.
The child process reads data from stdin and writes to stdout after processing. I've got all the communication pipes set up so I can pass input data from the main process to the child, and read the output the other way, this all works fine (nonblocking to avoid deadlocks, etc). The child process lives as long as it takes for the main process to receive the (finite) input stream from an external source.
The question I have is about the pipe handles themselves. The main process informs the child that the input stream has completed by calling close()
on the pipe attached to the child's stdin. This works as long as the only handle to the write end of that pipe is held by the main process. What if the main process, for some other unrelated reason, decides to fork? This would then create two handles to the write end of the pipe, meaning when I try to close the write end of the stdin pipe, the child won't notice because there is still another handle to the write end open. That other open handle is out of my control.
I know there is the FD_CLOEXEC
bit that I can set on a file descriptor so that it is automatically closed when an exec()
is done. However, this won't protect against the case where the main process forks but does not exec.
What's the general solution to this problem? I can think of only a couple of ideas:
- Ensure (through inspection) that the existing process doesn't fork arbitrarily without also doing an exec. This may be possible but is not a general solution.
- At startup, fork a long-lived helper process whose sole responsibility is to periodically fork/exec the child that does the actual processing. That way the helper's handle context is known and can be well-controlled. However, this is annoying because the helper needs some way to know that the input stream has ended other than closing its stdin.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
很少没有标准系统库fork
而不执行。这很不寻常。 Unix 或 Linux 中没有 close-on-fork 工具,我对 AIX 上的情况表示怀疑。如果您真的很关心的话,AIX 上有可加载的内核扩展。想必您知道用于关闭执行的fcntl
。如果你的同事正在编写无执行程序的分支,那么我无法提供太多帮助。Very fewNo standard system librariesfork
without exec. It's quite unusual. There is no close-on-fork facility in Unix or Linux, and I doubt it on AIX. There are loadable kernel extensions on AIX if you really care that much. Presumably you know aboutfcntl
for close on exec. If your co-workers are writing exec-less forks, then I can't offer much assistance.