Description
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
:
cpython/Lib/multiprocessing/shared_memory.py
Lines 109 to 117 in 973a520
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