SharedMemory constructor raises "cannot mmap an empty file" exception

未关闭
#92,408 2 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
3/5
预计耗时
1-2 天
新手友好度
35/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
停滞
技术栈
python

调研方向

从 Lib/multiprocessing/shared_memory.py 中的 SharedMemory 构造函数开始,检查 mmap.mmap 周围的异常处理路径。在受影响的平台上运行 issue 中所示的复现步骤,然后检查关联的 PR gh-133227。完成的标准是:大小为零的共享内存对象可以通过标准库路径进行清理,而不会让 ValueError 未经处理。

由索引模型根据 Issue 内容生成。

描述

stdlib topic-multiprocessing type-bug

Bug report

I was trying to clean up a shared memory object left behind by an earlier process using the following code:

shm = SharedMemory("some_name")
shm.close()
shm.unlink()

However, the first line resulted in an exception being raised:

  File "/home/USER/.pyenv/versions/3.9.10/lib/python3.9/multiprocessing/shared_memory.py", line 114, in __init__
    self._mmap = mmap.mmap(self._fd, size)
ValueError: cannot mmap an empty file

The exception handler around that line unlinks the object in case of an OSError, but not in case of this ValueError raised by mmap.mmap:

https://github.com/python/cpython/blob/973a5203c151efb7a86a478140f7b0c9ae70438f/Lib/multiprocessing/shared_memory.py#L109-L117

This makes it effectively impossible to clean up this particular shared memory object through the standard library.

I'm not sure how the shared memory object was corrupted in the first place, but it looks like the exception is triggered because os.fstat states that it has size 0:

>>> f = _posixshmem.shm_open('some_name', os.O_RDWR, mode=0o600)
>>> os.fstat(f)
os.stat_result(st_mode=33152, st_ino=80, st_dev=27, st_nlink=1, st_uid=1000, st_gid=1000, st_size=0, st_atime=1651836036, st_mtime=1651836036, st_ctime=1651836036)

After which the code tries to mmap with size 0 and fails with the exception mentioned earlier.

I was only able to resolve this by calling _posixshmem.shm_unlink('some_name') manually. I think the exception handler should be extended to also unlink the file if it was truncated to 0 like this.

This scenario can be reproduced with the following code:

import _posixshmem
import os
from multiprocessing.shared_memory import SharedMemory

f = _posixshmem.shm_open('test', os.O_RDWR | os.O_CREAT | os.O_EXCL, 0o600)
os.close(f)

try:
    mem = SharedMemory("test")
finally:
    _posixshmem.shm_unlink("test")

Your environment

  • CPython versions tested on: 3.9.10
  • Operating system and architecture: Ubuntu 20.04.3 LTS
Linked PRs
  • gh-133227
主要语言
Python
星标
77.2k
派生
36k
平均合并
1 天 9 小时
30 天内合并 PR
558

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

python/cpython 的其他 Issue

查看 python/cpython 的全部 Issue

相似的 Issue

更多 Python Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。