Python multiprocessing模块文件描述符泄露

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

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

因为最近公司的某个项目需要对接依图科技的实时语音转写服务,但由于对方只提供了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

### 迅投 QMT 平台使用 `multiprocessing` 模块遇到的问题及解决方案 在迅投 QMT 平台中应用 Python 的 `multiprocessing` 模块时可能会遭遇若干挑战,这些问题主要源于进程间通信、资源分配以及操作系统层面的支持差异。 #### 1. Windows 和 Linux 下启动方式不同引发的错误 由于 Windows 和 Unix-like 系统(如 Linux 或 macOS)对于子进程创建机制存在本质区别,在跨平台开发过程中容易出现兼容性问题。Windows 使用的是 spawn 方式来初始化新的Python解释器实例并执行目标函数;而在大多数类Unix系统上,默认采用 fork 方法复制当前进程环境给新进程[^1]。如果程序逻辑依赖于特定的操作系统行为,则可能导致移植困难或不可预见的行为异常。 ```python if __name__ == '__main__': import multiprocessing as mp # 设置启动模式为 'spawn' 可提高代码可移植性和稳定性 mp.set_start_method('spawn') process = mp.Process(target=worker_function, args=(arg,)) process.start() process.join() ``` #### 2. 数据共享与同步难题 当多个进程中需要访问相同的变量或数据结构时,必须小心处理竞争条件和死锁风险。虽然 `multiprocessing.Manager()` 提供了一种简单的方法来管理共享状态,但它会带来额外开销,并可能成为性能瓶颈。因此建议尽可能减少全局状态的数量,转而通过参数传递所需的数据副本给各个工作单元独立操作。 ```python from multiprocessing import Manager def worker(shared_list): shared_list.append(42) manager = Manager() shared_data = manager.list([1, 2, 3]) p = Process(target=worker, args=(shared_data,)) p.start(); p.join() print(list(shared_data)) # 输出: [1, 2, 3, 42] ``` #### 3. 资源泄漏隐患 不当关闭文件描述符或其他外部连接(数据库链接池、网络套接字等),会在长时间运行的应用场景下累积未释放的句柄数量直至耗尽可用资源。确保所有打开的对象都能及时回收非常重要,尤其是在多进程环境中更需谨慎对待此类细节以免造成难以排查的服务中断现象。 ```python import os from contextlib import closing from multiprocessing import Pool def safe_file_operation(filename): with open(filename, 'r') as f: content = f.read() return len(content) with closing(Pool(processes=4)) as pool: results = pool.map(safe_file_operation, ['file1.txt', 'file2.txt']) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值