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.
This commit is contained in:
parent
304a1b3f3a
commit
dc824c5dc1
@ -74,8 +74,8 @@ except ModuleNotFoundError:
|
|||||||
else:
|
else:
|
||||||
_mswindows = True
|
_mswindows = True
|
||||||
|
|
||||||
# wasm32-emscripten and wasm32-wasi do not support processes
|
# some platforms do not support subprocesses
|
||||||
_can_fork_exec = sys.platform not in {"emscripten", "wasi"}
|
_can_fork_exec = sys.platform not in {"emscripten", "wasi", "ios", "tvos", "watchos"}
|
||||||
|
|
||||||
if _mswindows:
|
if _mswindows:
|
||||||
import _winapi
|
import _winapi
|
||||||
@ -103,18 +103,22 @@ else:
|
|||||||
if _can_fork_exec:
|
if _can_fork_exec:
|
||||||
from _posixsubprocess import fork_exec as _fork_exec
|
from _posixsubprocess import fork_exec as _fork_exec
|
||||||
# used in methods that are called by __del__
|
# used in methods that are called by __del__
|
||||||
_waitpid = os.waitpid
|
class _del_safe:
|
||||||
_waitstatus_to_exitcode = os.waitstatus_to_exitcode
|
waitpid = os.waitpid
|
||||||
_WIFSTOPPED = os.WIFSTOPPED
|
waitstatus_to_exitcode = os.waitstatus_to_exitcode
|
||||||
_WSTOPSIG = os.WSTOPSIG
|
WIFSTOPPED = os.WIFSTOPPED
|
||||||
_WNOHANG = os.WNOHANG
|
WSTOPSIG = os.WSTOPSIG
|
||||||
|
WNOHANG = os.WNOHANG
|
||||||
|
ECHILD = errno.ECHILD
|
||||||
else:
|
else:
|
||||||
_fork_exec = None
|
class _del_safe:
|
||||||
_waitpid = None
|
waitpid = None
|
||||||
_waitstatus_to_exitcode = None
|
waitstatus_to_exitcode = None
|
||||||
_WIFSTOPPED = None
|
WIFSTOPPED = None
|
||||||
_WSTOPSIG = None
|
WSTOPSIG = None
|
||||||
_WNOHANG = None
|
WNOHANG = None
|
||||||
|
ECHILD = errno.ECHILD
|
||||||
|
|
||||||
import select
|
import select
|
||||||
import selectors
|
import selectors
|
||||||
|
|
||||||
@ -1951,20 +1955,16 @@ class Popen:
|
|||||||
raise child_exception_type(err_msg)
|
raise child_exception_type(err_msg)
|
||||||
|
|
||||||
|
|
||||||
def _handle_exitstatus(self, sts,
|
def _handle_exitstatus(self, sts, _del_safe=_del_safe):
|
||||||
_waitstatus_to_exitcode=_waitstatus_to_exitcode,
|
|
||||||
_WIFSTOPPED=_WIFSTOPPED,
|
|
||||||
_WSTOPSIG=_WSTOPSIG):
|
|
||||||
"""All callers to this function MUST hold self._waitpid_lock."""
|
"""All callers to this function MUST hold self._waitpid_lock."""
|
||||||
# This method is called (indirectly) by __del__, so it cannot
|
# This method is called (indirectly) by __del__, so it cannot
|
||||||
# refer to anything outside of its local scope.
|
# refer to anything outside of its local scope.
|
||||||
if _WIFSTOPPED(sts):
|
if _del_safe.WIFSTOPPED(sts):
|
||||||
self.returncode = -_WSTOPSIG(sts)
|
self.returncode = -_del_safe.WSTOPSIG(sts)
|
||||||
else:
|
else:
|
||||||
self.returncode = _waitstatus_to_exitcode(sts)
|
self.returncode = _del_safe.waitstatus_to_exitcode(sts)
|
||||||
|
|
||||||
def _internal_poll(self, _deadstate=None, _waitpid=_waitpid,
|
def _internal_poll(self, _deadstate=None, _del_safe=_del_safe):
|
||||||
_WNOHANG=_WNOHANG, _ECHILD=errno.ECHILD):
|
|
||||||
"""Check if child process has terminated. Returns returncode
|
"""Check if child process has terminated. Returns returncode
|
||||||
attribute.
|
attribute.
|
||||||
|
|
||||||
@ -1980,13 +1980,13 @@ class Popen:
|
|||||||
try:
|
try:
|
||||||
if self.returncode is not None:
|
if self.returncode is not None:
|
||||||
return self.returncode # Another thread waited.
|
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:
|
if pid == self.pid:
|
||||||
self._handle_exitstatus(sts)
|
self._handle_exitstatus(sts)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if _deadstate is not None:
|
if _deadstate is not None:
|
||||||
self.returncode = _deadstate
|
self.returncode = _deadstate
|
||||||
elif e.errno == _ECHILD:
|
elif e.errno == _del_safe.ECHILD:
|
||||||
# This happens if SIGCLD is set to be ignored or
|
# This happens if SIGCLD is set to be ignored or
|
||||||
# waiting for child processes has otherwise been
|
# waiting for child processes has otherwise been
|
||||||
# disabled for our process. This child is dead, we
|
# disabled for our process. This child is dead, we
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
The use of del-safe symbols in ``subprocess`` was refactored to allow for use in cross-platform build environments.
|
Loading…
x
Reference in New Issue
Block a user