aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Lib/asyncio/unix_events.py
diff options
context:
space:
mode:
authorshadchin <shadchin@yandex-team.com>2024-02-12 07:53:52 +0300
committershadchin <shadchin@yandex-team.com>2024-02-12 08:07:36 +0300
commitce1b7ca3171f9158180640c6a02a74b4afffedea (patch)
treee47c1e8391b1b0128262c1e9b1e6ed4c8fff2348 /contrib/tools/python3/src/Lib/asyncio/unix_events.py
parent57350d96f030db90f220ce50ee591d5c5d403df7 (diff)
downloadydb-ce1b7ca3171f9158180640c6a02a74b4afffedea.tar.gz
Update Python from 3.11.8 to 3.12.2
Diffstat (limited to 'contrib/tools/python3/src/Lib/asyncio/unix_events.py')
-rw-r--r--contrib/tools/python3/src/Lib/asyncio/unix_events.py108
1 files changed, 66 insertions, 42 deletions
diff --git a/contrib/tools/python3/src/Lib/asyncio/unix_events.py b/contrib/tools/python3/src/Lib/asyncio/unix_events.py
index 77d2670f83..f2e920ada4 100644
--- a/contrib/tools/python3/src/Lib/asyncio/unix_events.py
+++ b/contrib/tools/python3/src/Lib/asyncio/unix_events.py
@@ -195,22 +195,25 @@ class _UnixSelectorEventLoop(selector_events.BaseSelectorEventLoop):
async def _make_subprocess_transport(self, protocol, args, shell,
stdin, stdout, stderr, bufsize,
extra=None, **kwargs):
- with events.get_child_watcher() as watcher:
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ watcher = events.get_child_watcher()
+
+ with watcher:
if not watcher.is_active():
# Check early.
# Raising exception before process creation
# prevents subprocess execution if the watcher
# is not ready to handle it.
raise RuntimeError("asyncio.get_child_watcher() is not activated, "
- "subprocess support is not installed.")
+ "subprocess support is not installed.")
waiter = self.create_future()
transp = _UnixSubprocessTransport(self, protocol, args, shell,
- stdin, stdout, stderr, bufsize,
- waiter=waiter, extra=extra,
- **kwargs)
-
+ stdin, stdout, stderr, bufsize,
+ waiter=waiter, extra=extra,
+ **kwargs)
watcher.add_child_handler(transp.get_pid(),
- self._child_watcher_callback, transp)
+ self._child_watcher_callback, transp)
try:
await waiter
except (SystemExit, KeyboardInterrupt):
@@ -223,8 +226,7 @@ class _UnixSelectorEventLoop(selector_events.BaseSelectorEventLoop):
return transp
def _child_watcher_callback(self, pid, returncode, transp):
- # Skip one iteration for callbacks to be executed
- self.call_soon_threadsafe(self.call_soon, transp._process_exited, returncode)
+ self.call_soon_threadsafe(transp._process_exited, returncode)
async def create_unix_connection(
self, protocol_factory, path=None, *,
@@ -851,6 +853,13 @@ class AbstractChildWatcher:
waitpid(-1), there should be only one active object per process.
"""
+ def __init_subclass__(cls) -> None:
+ if cls.__module__ != __name__:
+ warnings._deprecated("AbstractChildWatcher",
+ "{name!r} is deprecated as of Python 3.12 and will be "
+ "removed in Python {remove}.",
+ remove=(3, 14))
+
def add_child_handler(self, pid, callback, *args):
"""Register a new child handler.
@@ -919,10 +928,6 @@ class PidfdChildWatcher(AbstractChildWatcher):
recent (5.3+) kernels.
"""
- def __init__(self):
- self._loop = None
- self._callbacks = {}
-
def __enter__(self):
return self
@@ -930,35 +935,22 @@ class PidfdChildWatcher(AbstractChildWatcher):
pass
def is_active(self):
- return self._loop is not None and self._loop.is_running()
+ return True
def close(self):
- self.attach_loop(None)
+ pass
def attach_loop(self, loop):
- if self._loop is not None and loop is None and self._callbacks:
- warnings.warn(
- 'A loop is being detached '
- 'from a child watcher with pending handlers',
- RuntimeWarning)
- for pidfd, _, _ in self._callbacks.values():
- self._loop._remove_reader(pidfd)
- os.close(pidfd)
- self._callbacks.clear()
- self._loop = loop
+ pass
def add_child_handler(self, pid, callback, *args):
- existing = self._callbacks.get(pid)
- if existing is not None:
- self._callbacks[pid] = existing[0], callback, args
- else:
- pidfd = os.pidfd_open(pid)
- self._loop._add_reader(pidfd, self._do_wait, pid)
- self._callbacks[pid] = pidfd, callback, args
+ loop = events.get_running_loop()
+ pidfd = os.pidfd_open(pid)
+ loop._add_reader(pidfd, self._do_wait, pid, pidfd, callback, args)
- def _do_wait(self, pid):
- pidfd, callback, args = self._callbacks.pop(pid)
- self._loop._remove_reader(pidfd)
+ def _do_wait(self, pid, pidfd, callback, args):
+ loop = events.get_running_loop()
+ loop._remove_reader(pidfd)
try:
_, status = os.waitpid(pid, 0)
except ChildProcessError:
@@ -976,12 +968,9 @@ class PidfdChildWatcher(AbstractChildWatcher):
callback(pid, returncode, *args)
def remove_child_handler(self, pid):
- try:
- pidfd, _, _ = self._callbacks.pop(pid)
- except KeyError:
- return False
- self._loop._remove_reader(pidfd)
- os.close(pidfd)
+ # asyncio never calls remove_child_handler() !!!
+ # The method is no-op but is implemented because
+ # abstract base classes require it.
return True
@@ -1049,6 +1038,13 @@ class SafeChildWatcher(BaseChildWatcher):
big number of children (O(n) each time SIGCHLD is raised)
"""
+ def __init__(self):
+ super().__init__()
+ warnings._deprecated("SafeChildWatcher",
+ "{name!r} is deprecated as of Python 3.12 and will be "
+ "removed in Python {remove}.",
+ remove=(3, 14))
+
def close(self):
self._callbacks.clear()
super().close()
@@ -1127,6 +1123,10 @@ class FastChildWatcher(BaseChildWatcher):
self._lock = threading.Lock()
self._zombies = {}
self._forks = 0
+ warnings._deprecated("FastChildWatcher",
+ "{name!r} is deprecated as of Python 3.12 and will be "
+ "removed in Python {remove}.",
+ remove=(3, 14))
def close(self):
self._callbacks.clear()
@@ -1239,6 +1239,10 @@ class MultiLoopChildWatcher(AbstractChildWatcher):
def __init__(self):
self._callbacks = {}
self._saved_sighandler = None
+ warnings._deprecated("MultiLoopChildWatcher",
+ "{name!r} is deprecated as of Python 3.12 and will be "
+ "removed in Python {remove}.",
+ remove=(3, 14))
def is_active(self):
return self._saved_sighandler is not None
@@ -1423,6 +1427,17 @@ class ThreadedChildWatcher(AbstractChildWatcher):
self._threads.pop(expected_pid)
+def can_use_pidfd():
+ if not hasattr(os, 'pidfd_open'):
+ return False
+ try:
+ pid = os.getpid()
+ os.close(os.pidfd_open(pid, 0))
+ except OSError:
+ # blocked by security policy like SECCOMP
+ return False
+ return True
+
class _UnixDefaultEventLoopPolicy(events.BaseDefaultEventLoopPolicy):
"""UNIX event loop policy with a watcher for child processes."""
@@ -1435,7 +1450,10 @@ class _UnixDefaultEventLoopPolicy(events.BaseDefaultEventLoopPolicy):
def _init_watcher(self):
with events._lock:
if self._watcher is None: # pragma: no branch
- self._watcher = ThreadedChildWatcher()
+ if can_use_pidfd():
+ self._watcher = PidfdChildWatcher()
+ else:
+ self._watcher = ThreadedChildWatcher()
def set_event_loop(self, loop):
"""Set the event loop.
@@ -1459,6 +1477,9 @@ class _UnixDefaultEventLoopPolicy(events.BaseDefaultEventLoopPolicy):
if self._watcher is None:
self._init_watcher()
+ warnings._deprecated("get_child_watcher",
+ "{name!r} is deprecated as of Python 3.12 and will be "
+ "removed in Python {remove}.", remove=(3, 14))
return self._watcher
def set_child_watcher(self, watcher):
@@ -1470,6 +1491,9 @@ class _UnixDefaultEventLoopPolicy(events.BaseDefaultEventLoopPolicy):
self._watcher.close()
self._watcher = watcher
+ warnings._deprecated("set_child_watcher",
+ "{name!r} is deprecated as of Python 3.12 and will be "
+ "removed in Python {remove}.", remove=(3, 14))
SelectorEventLoop = _UnixSelectorEventLoop