https://github.com/python/cpython/commit/646b453a15eecf66c02793751718a937147d0c15
commit: 646b453a15eecf66c02793751718a937147d0c15
branch: 3.13
author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com>
committer: vstinner <vstin...@python.org>
date: 2025-03-20T17:08:58Z
summary:

[3.13] gh-88887: Cleanup `multiprocessing.resource_tracker.ResourceTracker` 
upon deletion (GH-130429) (#131516)

gh-88887: Cleanup `multiprocessing.resource_tracker.ResourceTracker` upon 
deletion (GH-130429)
(cherry picked from commit f53e7de6a84a0f535efb75c3671283b801a1af0f)

Co-authored-by: luccabb <32229669+lucc...@users.noreply.github.com>
Co-authored-by: Victor Stinner <vstin...@python.org>
Co-authored-by: Gregory P. Smith <g...@krypto.org>

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-02-21-14-47-46.gh-issue-88887.V3U0CV.rst
M Lib/multiprocessing/resource_tracker.py

diff --git a/Lib/multiprocessing/resource_tracker.py 
b/Lib/multiprocessing/resource_tracker.py
index 90e036ae905afa..05633ac21a259c 100644
--- a/Lib/multiprocessing/resource_tracker.py
+++ b/Lib/multiprocessing/resource_tracker.py
@@ -75,29 +75,53 @@ 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
-
-            # closing the "alive" file descriptor stops main()
-            os.close(self._fd)
-            self._fd = None
+    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)
+
+    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()
+
+    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
 
-            _, status = os.waitpid(self._pid, 0)
+        _, status = waitpid(self._pid, 0)
 
-            self._pid = None
+        self._pid = None
 
-            try:
-                self._exitcode = os.waitstatus_to_exitcode(status)
-            except ValueError:
-                # os.waitstatus_to_exitcode may raise an exception for invalid 
values
-                self._exitcode = None
+        try:
+            self._exitcode = waitstatus_to_exitcode(status)
+        except ValueError:
+            # os.waitstatus_to_exitcode may raise an exception for invalid 
values
+            self._exitcode = None
 
     def getfd(self):
         self.ensure_running()
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-21-14-47-46.gh-issue-88887.V3U0CV.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-21-14-47-46.gh-issue-88887.V3U0CV.rst
new file mode 100644
index 00000000000000..1a6c9483e2a35e
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-21-14-47-46.gh-issue-88887.V3U0CV.rst
@@ -0,0 +1 @@
+Fixing multiprocessing Resource Tracker process leaking, usually observed when 
running Python as PID 1.

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to