如何在不泄漏手柄的情况下实现本地IPC(跨平台)?

2024-09-30 22:19:19 发布

您现在位置:Python中文网/ 问答频道 /正文

如何用子进程启动IPC,而不让它继承所有句柄?为了让它更有趣,它应该可以在windows和unix上运行。在

背景:我正在编写一个与3rparty共享库(我们称之为它)接口的库,而3rparty共享库又包含全局数据(实际上应该是对象!)。我想要这个全局数据的多个实例。据我所知,我有两个选择来解决这个问题:

  1. 创建一个cython模块,该模块链接到它的静态变量,然后在需要新实例时复制并导入该模块。类似地,我可以复制它,但是创建ctypes接口需要更多的工作。

  2. 生成一个子进程来加载它并与之建立IPC连接。

使用(2)的原因如下:

  • 我不确定,如果(1)在任何方面都是可靠的,并且感觉是一个坏主意(当应用程序以不受控制的方式退出时,所有额外的模块会发生什么情况?)。

  • 不管怎样,出于安全考虑,将它封装到一个单独的进程中实际上可能是一个好主意:它处理潜在的不安全输入,并且它的代码质量不是太好。所以,我不希望在运行它时打开任何安全资源。

  • 在未来的应用中,这种IPC可能会有很多需求

我有什么选择?我已经调查过:

  • multiprocessing.Process起初看起来不错,直到我意识到新进程得到了我所有句柄的副本。不用说,这是相当有问题的,因为现在不能通过在父进程中关闭资源来可靠地释放资源+前面提到的安全问题。

  • multiprocessing.Process中使用os.closerange手动关闭所有句柄-除了我感兴趣的管道。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?但如果你只知道部分问题的答案,请不要犹豫回答。在

感谢您抽出时间来阅读!在


Tags: 模块数据对象实例进程oswindowsunix
1条回答
网友
1楼 · 发布于 2024-09-30 22:19:19

在python>;=3.4subprocess.Popen(..., stdin=PIPE, stdout=PIPE, close_fds=False)似乎是一个可能的选择。这是由于修补程序使所有打开的文件描述符在默认情况下不可继承。更准确地说,它们将在execv上自动关闭(因此仍然不能使用multiprocessing.Process),请参见PEP 446。在

对于其他python版本,这也是一个有效的选项:

  • 在windows上,默认情况下创建的句柄是不可继承的,因此您将只泄漏显式设置为可继承的句柄
  • 仍然可以使用python/POSIX;=3os.近距离在生成子进程后关闭打开的文件描述符

有关相应的示例,请参见:

https://github.com/coldfix/python-ipc-test

最有用的组合是:

  1. 在stdio:泡菜在

    • 专业版:在我的测试中完全跨平台
    • 专业版:最快选项(2)
    • con:stdin/stdout不能独立重定向
  2. 继承_裁研所:泡菜在

    • pro:您可以独立重定向STDIO流
    • 专业版:最快选项与stdio:泡菜在
    • 缺点:非常低级的平台特定代码
  3. 在承插:承插管在

    • 专业:轻松跨平台
    • 缺点:在短时间内,“攻击者”可能会连接到端口,您可能需要密码或其他东西来防止这种情况发生
    • 缺点:略慢于windows上的备选方案(在我的测量中,系数为1.6)
    • 当不使用AF iu UNIX时,linux上的性能会受到不可预测的影响

相关问题 更多 >