summaryrefslogtreecommitdiffstats
path: root/Lib/subprocess.py
diff options
context:
space:
mode:
authorRussell Keith-Magee <russell@keith-magee.com>2023-12-05 04:23:17 (GMT)
committerGitHub <noreply@github.com>2023-12-05 04:23:17 (GMT)
commitdc824c5dc120ffed84bafd23f95e95a99678ed6a (patch)
tree8e8150f7177670debe9381ac2a7b5232fe358d6b /Lib/subprocess.py
parent304a1b3f3a8ed9a734ef1d098cafccb6725162db (diff)
downloadcpython-dc824c5dc120ffed84bafd23f95e95a99678ed6a.zip
cpython-dc824c5dc120ffed84bafd23f95e95a99678ed6a.tar.gz
cpython-dc824c5dc120ffed84bafd23f95e95a99678ed6a.tar.bz2
gh-112736: Refactor del-safe symbol handling in subprocess (#112738)
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.
Diffstat (limited to 'Lib/subprocess.py')
-rw-r--r--Lib/subprocess.py48
1 files changed, 24 insertions, 24 deletions
diff --git a/Lib/subprocess.py b/Lib/subprocess.py
index 6df5dd5..d6edd1a 100644
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -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