Repeated creation of ProcessPoolExecutor leads to "Too many open files"
Nessuno ha ancora preso questa issue.
- Lingua principale
- Python
- Stelle
- 77.2k
- Fork
- 35.9k
- Metriche di merge delle PR
- Metriche PR in attesa
Descrizione
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
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Inizia riproducendo l'esempio con concurrent.futures.process.ProcessPoolExecutor, quindi leggi concurrent/futures/process.py e i file spawn di multiprocessing a cui si fa riferimento. Traccia il ciclo di vita dell'executor e il comportamento del garbage collector durante creazioni ripetute. Il lavoro è completato quando gli executor creati ripetutamente non esauriscono più i descrittori di file nelle versioni di Python e nel sistema operativo segnalati, con un test di regressione che copra il caso.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- python
- Ambito
- backend
- Tipo di issue
- Bug
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Stato di attività
- Ferma
- Chiarezza
- Da chiarire
- Idoneità per principianti
- 35/100