如何使用子进程启动 IPC,而不让它继承所有句柄?为了让它更有趣,这应该在 Windows 和 unix 上工作。
背景:我正在编写一个与 3rparty 共享库(我们称之为 IT)接口的库,该库又包含全局数据(真的应该是对象!)。我想要这个全局数据的多个实例。据我了解,我有两种选择来解决这个问题:
创建一个与 IT 的静态变体链接的 cython 模块,然后在我需要新实例时复制并导入该模块。类似地,我可以复制 IT,但创建 ctypes 接口需要更多的工作。
生成一个加载 IT 并建立到它的 IPC 连接的子进程。
使用 (2) 有几个原因:
我不确定,如果(1)在任何方面都是可靠的并且感觉是个坏主意(当应用程序以不受控制的方式退出时,所有额外的模块会发生什么?)。
出于安全考虑,将 IT 打包到一个单独的流程中实际上可能是一个好主意:IT 处理潜在的不安全输入,并且 IT 的代码质量并不太好。所以,我宁愿在运行它时不要打开任何安全资源。
在未来的应用中可能会大量需要这种 IPC
那么我的选择是什么?我已经研究过:
multiprocessing.Process
起初看起来不错,直到我意识到新进程获取了我所有句柄的副本。不用说这是相当有问题的,因为现在无法通过在父进程中关闭它们来可靠地释放资源 + 前面提到的安全问题。os.closerange
在 a中使用multiprocessing.Process
手动关闭所有句柄 - 除了我感兴趣的管道。是os.closerange
只关闭文件还是它也处理其他类型的资源?如果是这样:给定对象,我如何确定范围Pipe
?subprocess.Popen(.., close_fds=True, stdin=PIPE, stdout=PIPE)
在 unix 上工作正常,但在 win32 上是不可能的。命名管道在 win32 和 unix 上非常不同。他们有没有他们使用的图书馆?
插座。很有希望,特别是因为它们是可以使用套接字的方便的 RPC 库。另一方面,我担心这可能会导致一大堆安全问题。我已确定为本地来源 (
sock.getpeername()[0] == '127.0.0.1'
) 的套接字是否可以防止回火?
有没有我忽略的可能性?
总结一下:主要问题是如何在 windows+unix 上建立一个带有子进程的安全 IPC?但是,如果您只知道部分问题的答案,请不要犹豫。
感谢您花时间阅读它!