]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-112736: Refactor del-safe symbol handling in subprocess (#112738)
authorRussell Keith-Magee <russell@keith-magee.com>
Tue, 5 Dec 2023 04:23:17 +0000 (12:23 +0800)
committerGitHub <noreply@github.com>
Tue, 5 Dec 2023 04:23:17 +0000 (20:23 -0800)
Refactor delete-safe symbol handling in subprocess.

Only module globals are force-cleared during interpreter finalization, using a class reference instead of individually listing the constants everywhere is simpler.

Lib/subprocess.py
Misc/NEWS.d/next/Library/2023-12-05-01-19-28.gh-issue-112736.rdHDrU.rst [new file with mode: 0644]

index 6df5dd551ea67e9d9651f636f5a399eae9f999dd..d6edd1a9807d1bee9c44dafd0c2c12d22a2b537c 100644 (file)
@@ -74,8 +74,8 @@ except ModuleNotFoundError:
 else:
     _mswindows = True
 
-# wasm32-emscripten and wasm32-wasi do not support processes
-_can_fork_exec = sys.platform not in {"emscripten", "wasi"}
+# some platforms do not support subprocesses
+_can_fork_exec = sys.platform not in {"emscripten", "wasi", "ios", "tvos", "watchos"}
 
 if _mswindows:
     import _winapi
@@ -103,18 +103,22 @@ else:
     if _can_fork_exec:
         from _posixsubprocess import fork_exec as _fork_exec
         # used in methods that are called by __del__
-        _waitpid = os.waitpid
-        _waitstatus_to_exitcode = os.waitstatus_to_exitcode
-        _WIFSTOPPED = os.WIFSTOPPED
-        _WSTOPSIG = os.WSTOPSIG
-        _WNOHANG = os.WNOHANG
+        class _del_safe:
+            waitpid = os.waitpid
+            waitstatus_to_exitcode = os.waitstatus_to_exitcode
+            WIFSTOPPED = os.WIFSTOPPED
+            WSTOPSIG = os.WSTOPSIG
+            WNOHANG = os.WNOHANG
+            ECHILD = errno.ECHILD
     else:
-        _fork_exec = None
-        _waitpid = None
-        _waitstatus_to_exitcode = None
-        _WIFSTOPPED = None
-        _WSTOPSIG = None
-        _WNOHANG = None
+        class _del_safe:
+            waitpid = None
+            waitstatus_to_exitcode = None
+            WIFSTOPPED = None
+            WSTOPSIG = None
+            WNOHANG = None
+            ECHILD = errno.ECHILD
+
     import select
     import selectors
 
@@ -1951,20 +1955,16 @@ class Popen:
                 raise child_exception_type(err_msg)
 
 
-        def _handle_exitstatus(self, sts,
-                               _waitstatus_to_exitcode=_waitstatus_to_exitcode,
-                               _WIFSTOPPED=_WIFSTOPPED,
-                               _WSTOPSIG=_WSTOPSIG):
+        def _handle_exitstatus(self, sts, _del_safe=_del_safe):
             """All callers to this function MUST hold self._waitpid_lock."""
             # This method is called (indirectly) by __del__, so it cannot
             # refer to anything outside of its local scope.
-            if _WIFSTOPPED(sts):
-                self.returncode = -_WSTOPSIG(sts)
+            if _del_safe.WIFSTOPPED(sts):
+                self.returncode = -_del_safe.WSTOPSIG(sts)
             else:
-                self.returncode = _waitstatus_to_exitcode(sts)
+                self.returncode = _del_safe.waitstatus_to_exitcode(sts)
 
-        def _internal_poll(self, _deadstate=None, _waitpid=_waitpid,
-                _WNOHANG=_WNOHANG, _ECHILD=errno.ECHILD):
+        def _internal_poll(self, _deadstate=None, _del_safe=_del_safe):
             """Check if child process has terminated.  Returns returncode
             attribute.
 
@@ -1980,13 +1980,13 @@ class Popen:
                 try:
                     if self.returncode is not None:
                         return self.returncode  # Another thread waited.
-                    pid, sts = _waitpid(self.pid, _WNOHANG)
+                    pid, sts = _del_safe.waitpid(self.pid, _del_safe.WNOHANG)
                     if pid == self.pid:
                         self._handle_exitstatus(sts)
                 except OSError as e:
                     if _deadstate is not None:
                         self.returncode = _deadstate
-                    elif e.errno == _ECHILD:
+                    elif e.errno == _del_safe.ECHILD:
                         # This happens if SIGCLD is set to be ignored or
                         # waiting for child processes has otherwise been
                         # disabled for our process.  This child is dead, we
diff --git a/Misc/NEWS.d/next/Library/2023-12-05-01-19-28.gh-issue-112736.rdHDrU.rst b/Misc/NEWS.d/next/Library/2023-12-05-01-19-28.gh-issue-112736.rdHDrU.rst
new file mode 100644 (file)
index 0000000..6c09e62
--- /dev/null
@@ -0,0 +1 @@
+The use of del-safe symbols in ``subprocess`` was refactored to allow for use in cross-platform build environments.