[3.12] gh-88887: Cleanup multiprocessing.resource_tracker.ResourceTracker upon deletion (GH-130429) (#131530)

Co-authored-by: Victor Stinner <vstinner@python.org>
Co-authored-by: Gregory P. Smith <greg@krypto.org>
(cherry picked from commit f53e7de6a8)
This commit is contained in:
luccabb 2025-03-21 03:15:35 -07:00 committed by GitHub
parent 30e38b9dc6
commit 3d1f8cae48
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 39 additions and 14 deletions

View file

@ -70,22 +70,46 @@ def _reentrant_call_error(self):
raise ReentrantCallError(
"Reentrant call into the multiprocessing resource tracker")
def _stop(self):
with self._lock:
# This should not happen (_stop() isn't called by a finalizer)
# but we check for it anyway.
if self._lock._recursion_count() > 1:
return self._reentrant_call_error()
if self._fd is None:
# not running
return
def __del__(self):
# making sure child processess are cleaned before ResourceTracker
# gets destructed.
# see https://github.com/python/cpython/issues/88887
self._stop(use_blocking_lock=False)
# closing the "alive" file descriptor stops main()
os.close(self._fd)
self._fd = None
def _stop(self, use_blocking_lock=True):
if use_blocking_lock:
with self._lock:
self._stop_locked()
else:
acquired = self._lock.acquire(blocking=False)
try:
self._stop_locked()
finally:
if acquired:
self._lock.release()
os.waitpid(self._pid, 0)
self._pid = None
def _stop_locked(
self,
close=os.close,
waitpid=os.waitpid,
waitstatus_to_exitcode=os.waitstatus_to_exitcode,
):
# This shouldn't happen (it might when called by a finalizer)
# so we check for it anyway.
if self._lock._recursion_count() > 1:
return self._reentrant_call_error()
if self._fd is None:
# not running
return
if self._pid is None:
return
# closing the "alive" file descriptor stops main()
close(self._fd)
self._fd = None
waitpid(self._pid, 0)
self._pid = None
def getfd(self):
self.ensure_running()

View file

@ -0,0 +1 @@
Fixing multiprocessing Resource Tracker process leaking, usually observed when running Python as PID 1.