Skip to content

Commit 1eca259

Browse files
committed
[3.12] pythongh-112736: Refactor del-safe symbol handling in subprocess (python#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.
1 parent ff3bc82 commit 1eca259

File tree

2 files changed

+25
-24
lines changed

2 files changed

+25
-24
lines changed

Lib/subprocess.py

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@
7474
else:
7575
_mswindows = True
7676

77-
# wasm32-emscripten and wasm32-wasi do not support processes
78-
_can_fork_exec = sys.platform not in {"emscripten", "wasi"}
77+
# some platforms do not support subprocesses
78+
_can_fork_exec = sys.platform not in {"emscripten", "wasi", "ios", "tvos", "watchos"}
7979

8080
if _mswindows:
8181
import _winapi
@@ -103,18 +103,22 @@
103103
if _can_fork_exec:
104104
from _posixsubprocess import fork_exec as _fork_exec
105105
# used in methods that are called by __del__
106-
_waitpid = os.waitpid
107-
_waitstatus_to_exitcode = os.waitstatus_to_exitcode
108-
_WIFSTOPPED = os.WIFSTOPPED
109-
_WSTOPSIG = os.WSTOPSIG
110-
_WNOHANG = os.WNOHANG
106+
class _del_safe:
107+
waitpid = os.waitpid
108+
waitstatus_to_exitcode = os.waitstatus_to_exitcode
109+
WIFSTOPPED = os.WIFSTOPPED
110+
WSTOPSIG = os.WSTOPSIG
111+
WNOHANG = os.WNOHANG
112+
ECHILD = errno.ECHILD
111113
else:
112-
_fork_exec = None
113-
_waitpid = None
114-
_waitstatus_to_exitcode = None
115-
_WIFSTOPPED = None
116-
_WSTOPSIG = None
117-
_WNOHANG = None
114+
class _del_safe:
115+
waitpid = None
116+
waitstatus_to_exitcode = None
117+
WIFSTOPPED = None
118+
WSTOPSIG = None
119+
WNOHANG = None
120+
ECHILD = errno.ECHILD
121+
118122
import select
119123
import selectors
120124

@@ -1958,20 +1962,16 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
19581962
raise child_exception_type(err_msg)
19591963

19601964

1961-
def _handle_exitstatus(self, sts,
1962-
_waitstatus_to_exitcode=_waitstatus_to_exitcode,
1963-
_WIFSTOPPED=_WIFSTOPPED,
1964-
_WSTOPSIG=_WSTOPSIG):
1965+
def _handle_exitstatus(self, sts, _del_safe=_del_safe):
19651966
"""All callers to this function MUST hold self._waitpid_lock."""
19661967
# This method is called (indirectly) by __del__, so it cannot
19671968
# refer to anything outside of its local scope.
1968-
if _WIFSTOPPED(sts):
1969-
self.returncode = -_WSTOPSIG(sts)
1969+
if _del_safe.WIFSTOPPED(sts):
1970+
self.returncode = -_del_safe.WSTOPSIG(sts)
19701971
else:
1971-
self.returncode = _waitstatus_to_exitcode(sts)
1972+
self.returncode = _del_safe.waitstatus_to_exitcode(sts)
19721973

1973-
def _internal_poll(self, _deadstate=None, _waitpid=_waitpid,
1974-
_WNOHANG=_WNOHANG, _ECHILD=errno.ECHILD):
1974+
def _internal_poll(self, _deadstate=None, _del_safe=_del_safe):
19751975
"""Check if child process has terminated. Returns returncode
19761976
attribute.
19771977
@@ -1987,13 +1987,13 @@ def _internal_poll(self, _deadstate=None, _waitpid=_waitpid,
19871987
try:
19881988
if self.returncode is not None:
19891989
return self.returncode # Another thread waited.
1990-
pid, sts = _waitpid(self.pid, _WNOHANG)
1990+
pid, sts = _del_safe.waitpid(self.pid, _del_safe.WNOHANG)
19911991
if pid == self.pid:
19921992
self._handle_exitstatus(sts)
19931993
except OSError as e:
19941994
if _deadstate is not None:
19951995
self.returncode = _deadstate
1996-
elif e.errno == _ECHILD:
1996+
elif e.errno == _del_safe.ECHILD:
19971997
# This happens if SIGCLD is set to be ignored or
19981998
# waiting for child processes has otherwise been
19991999
# disabled for our process. This child is dead, we
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
The use of del-safe symbols in ``subprocess`` was refactored to allow for use in cross-platform build environments.

0 commit comments

Comments
 (0)