Python multiprocessing模块文件描述符泄露

本文探讨了在使用Python multiprocessing模块时遇到的文件描述符泄露问题。由于GIL限制,服务器采用accept-fork模式,但在运行一段时间后出现文件描述符溢出异常。通过lsof命令发现未关闭的PIPE,经分析发现multiprocessing的start方法创建的PIPE在子进程结束后未被关闭。为解决此问题,可以在父进程中使用OS.close()关闭sentinel,或者将其注册到selector中以非阻塞方式检测子进程结束。这是一个待测试的改进方案。
摘要由CSDN通过智能技术生成

背景

因为最近公司的某个项目需要对接依图科技的实时语音转写服务,但由于对方只提供了Java与Python的接口(其实依图科技的实时语音转写接口采用的是grpc,虽然我给领导提过可以让对方用proto文件快速生成其他语言的接口,但无赖领导没有采纳),而我们的产品是基于C/C++的,所以决定用Python写一个中转服务(如果开始知道Python这么多坑,我一定选Java)。

问题

由于GIL的存在,Python服务器就只能采用accept-fork模式,但服务运行一段时间后,抛出异常信息——文件描述符溢出——,确定fork前除了监听套接字与连接套接字外,没有创建其他文件描述符,而且fork之后在父进程关闭了连接套接字,在子进程关闭了监听套接字,理论上不应该存在文件描述符泄露。

解决方案

最后使用lsof命令查看父进程的相关记录,发现有未关闭的PIPE。后面查看multiprocessing的代码,发现start方法会默认创建一个PIPE用于与子进程通信,该pipe的描述符保存在sentinel字段,官网关于sentinel的描述

A numeric handle of a system object which will become “ready”
when the process ends.
You can use this value if you want to wait on several events at once using multiprocessing.connection.wait(). Otherwise calling join() is simpler.
O

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值