multiprocessing SharedMemory.__del__ can fail, leak file descriptor
还没有人认领这个 Issue。
- 主要语言
- Python
- 星标
- 77.2k
- 派生
- 35.9k
- PR 合并指标
- PR 指标待抓取
描述
Bug report
Bug description:
When a SharedMemory object goes out of scope, its __del__ method calls self.close() to clean it up. This can break if there is still a buffer exported from its mmap instance. It tries to close the mmap before the fd, so in this case it will leave the file descriptor open:
>>> from multiprocessing.shared_memory import SharedMemory
>>> import os
>>> def shview(size=4096):
... shmem = SharedMemory(create=True, size=size)
... print("fd is:", shmem._fd)
... return shmem.buf.cast('i')
...
>>> mv = shview()
fd is: 5
Exception ignored while calling deallocator <function SharedMemory.__del__ at 0x7f686264d640>:
Traceback (most recent call last):
File "/usr/lib64/python3.14/multiprocessing/shared_memory.py", line 189, in __del__
self.close()
File "/usr/lib64/python3.14/multiprocessing/shared_memory.py", line 232, in close
self._mmap.close()
BufferError: cannot close exported pointers exist
>>> os.fstat(5).st_size # fd still open
4096
I think a better option for __del__ would be to close the fd and leave the mmap & buf objects alone, to be cleaned up as normal by reference counting or GC:
>>> class SharedMemoryFix(SharedMemory):
... def __del__(self):
... if self._fd >= 0:
... os.close(self._fd)
... self._fd = -1
...
>>> def shview(size=4096):
... shmem = SharedMemoryFix(create=True, size=size)
... print("fd is:", shmem._fd)
... return shmem.buf.cast('i')
...
>>> mv = shview()
fd is: 7
>>> os.fstat(7)
Traceback (most recent call last):
File "<python-input-8>", line 1, in <module>
os.fstat(7)
~~~~~~~~^^^
OSError: [Errno 9] Bad file descriptor
(I'm thinking about the POSIX side here. IDK if the behaviour on Windows needs to be different, though I guess it can rely on the mmap's dealloc too)
CPython versions tested on:
3.14
Operating systems tested on:
Linux
Linked PRs
- gh-155007
- gh-155070
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
从 Lib/multiprocessing/shared_memory.py 中的 SharedMemory.del 和 close() 开始,使用 issue 中的 Linux 复现来观察导出缓冲区失败和泄漏的文件描述符。在开始之前检查链接的 PR gh-155007 和 gh-155070;完成意味着析构函数不再让描述符保持打开状态,同时保留相关的 mmap 和缓冲区行为。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- python
- 领域
- operating-systems
- Issue 类型
- 缺陷
- 难度
- 3/5
- 预计耗时
- 1-2 天
- 活跃度
- 停滞
- 描述清晰度
- 基本清楚
- 新手友好度
- 35/100