Repeated creation of ProcessPoolExecutor leads to "Too many open files"
Personne n'a encore pris cette issue.
- 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:
Running this code:
import concurrent.futures.process
for _ in range(100):
x = concurrent.futures.process.ProcessPoolExecutor()
x.submit(lambda: 42)
Results (most of the time) in an error indicating the system has run out of file descriptors, for example:
Traceback (most recent call last):
File "<python-input-3>", line 4, in <module>
x.submit(lambda: 42)
~~~~~~~~^^^^^^^^^^^^
File "/Users/jelle/.pyenv/versions/3.13.0rc2/lib/python3.13/concurrent/futures/process.py", line 811, in submit
self._adjust_process_count()
~~~~~~~~~~~~~~~~~~~~~~~~~~^^
File "/Users/jelle/.pyenv/versions/3.13.0rc2/lib/python3.13/concurrent/futures/process.py", line 770, in _adjust_process_count
self._spawn_process()
~~~~~~~~~~~~~~~~~~~^^
File "/Users/jelle/.pyenv/versions/3.13.0rc2/lib/python3.13/concurrent/futures/process.py", line 788, in _spawn_process
p.start()
~~~~~~~^^
File "/Users/jelle/.pyenv/versions/3.13.0rc2/lib/python3.13/multiprocessing/process.py", line 121, in start
self._popen = self._Popen(self)
~~~~~~~~~~~^^^^^^
File "/Users/jelle/.pyenv/versions/3.13.0rc2/lib/python3.13/multiprocessing/context.py", line 289, in _Popen
return Popen(process_obj)
File "/Users/jelle/.pyenv/versions/3.13.0rc2/lib/python3.13/multiprocessing/popen_spawn_posix.py", line 32, in __init__
super().__init__(process_obj)
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
File "/Users/jelle/.pyenv/versions/3.13.0rc2/lib/python3.13/multiprocessing/popen_fork.py", line 20, in __init__
self._launch(process_obj)
~~~~~~~~~~~~^^^^^^^^^^^^^
File "/Users/jelle/.pyenv/versions/3.13.0rc2/lib/python3.13/multiprocessing/popen_spawn_posix.py", line 53, in _launch
parent_r, child_w = os.pipe()
~~~~~~~^^
OSError: [Errno 24] Too many open files
The exact error varies. For example, one time the error happened on an os.getcwd() call. One time one of the futures printed as <Future at 0x1035b9950 state=finished raised PicklingError>.
I originally encountered this in the CI for Black, where it only happened on MacOS in 3.13, but the code sample above raises errors on 3.11 and 3.12 too when I run it locally. Still, it's possible that the GC changes in 3.13 make the problem more frequent.
Adding gc.collect() to the loop body fixes the problem. This suggests there is some cycle involving the executor that isn't getting collected until the GC kicks in.
CPython versions tested on:
3.11, 3.12, 3.13
Operating systems tested on:
macOS
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Piste de recherche
Commencez par reproduire l’exemple avec concurrent.futures.process.ProcessPoolExecutor, puis lisez concurrent/futures/process.py et les fichiers spawn de multiprocessing référencés. Suivez le cycle de vie de l’executor et le comportement du garbage collector lors de créations répétées. Le travail est terminé lorsque des executors créés à répétition n’épuisent plus les descripteurs de fichiers dans les versions de Python et le système d’exploitation signalés, avec un test de régression couvrant le cas.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- python
- Domaine
- backend
- Type d'issue
- Bug
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Activité
- À l'abandon
- Clarté
- À clarifier
- Accessibilité débutants
- 35/100