python / python/cpython

multiprocessing SharedMemory.__del__ can fail, leak file descriptor

Ouverte
#155,003 1 commentaire 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

stdlib topic-multiprocessing type-bug
Langage dominant
Python
Étoiles
77.2k
Forks
35.9k
Métriques de merge des PR
Métriques de PR en attente

Description

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

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez dans Lib/multiprocessing/shared_memory.py, au niveau de SharedMemory.del et close(), en utilisant la reproduction Linux de l’issue pour observer l’échec d’exportation du tampon et le descripteur de fichier laissé ouvert. Vérifiez les PR liées gh-155007 et gh-155070 avant de commencer ; le travail est terminé lorsque le destructeur ne laisse plus le descripteur ouvert, tout en préservant le comportement pertinent de mmap et du tampon.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
python
Domaine
operating-systems
Type d'issue
Bug
Difficulté
3/5
Temps estimé
1-2 jours
Activité
À l'abandon
Clarté
Plutôt claire
Accessibilité débutants
35/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.