aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Lib/asyncio/base_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/base_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/base_events.py')
-rw-r--r--contrib/tools/python3/src/Lib/asyncio/base_events.py63
1 files changed, 56 insertions, 7 deletions
diff --git a/contrib/tools/python3/src/Lib/asyncio/base_events.py b/contrib/tools/python3/src/Lib/asyncio/base_events.py
index 5fa28cae9c..c16c445bde 100644
--- a/contrib/tools/python3/src/Lib/asyncio/base_events.py
+++ b/contrib/tools/python3/src/Lib/asyncio/base_events.py
@@ -306,7 +306,7 @@ class Server(events.AbstractServer):
self._waiters = None
for waiter in waiters:
if not waiter.done():
- waiter.set_result(waiter)
+ waiter.set_result(None)
def _start_serving(self):
if self._serving:
@@ -378,7 +378,27 @@ class Server(events.AbstractServer):
self._serving_forever_fut = None
async def wait_closed(self):
- if self._sockets is None or self._waiters is None:
+ """Wait until server is closed and all connections are dropped.
+
+ - If the server is not closed, wait.
+ - If it is closed, but there are still active connections, wait.
+
+ Anyone waiting here will be unblocked once both conditions
+ (server is closed and all connections have been dropped)
+ have become true, in either order.
+
+ Historical note: In 3.11 and before, this was broken, returning
+ immediately if the server was already closed, even if there
+ were still active connections. An attempted fix in 3.12.0 was
+ still broken, returning immediately if the server was still
+ open and there were no active connections. Hopefully in 3.12.1
+ we have it right.
+ """
+ # Waiters are unblocked by self._wakeup(), which is called
+ # from two places: self.close() and self._detach(), but only
+ # when both conditions have become true. To signal that this
+ # has happened, self._wakeup() sets self._waiters to None.
+ if self._waiters is None:
return
waiter = self._loop.create_future()
self._waiters.append(waiter)
@@ -562,8 +582,13 @@ class BaseEventLoop(events.AbstractEventLoop):
'asyncgen': agen
})
- async def shutdown_default_executor(self):
- """Schedule the shutdown of the default executor."""
+ async def shutdown_default_executor(self, timeout=None):
+ """Schedule the shutdown of the default executor.
+
+ The timeout parameter specifies the amount of time the executor will
+ be given to finish joining. The default value is None, which means
+ that the executor will be given an unlimited amount of time.
+ """
self._executor_shutdown_called = True
if self._default_executor is None:
return
@@ -573,7 +598,13 @@ class BaseEventLoop(events.AbstractEventLoop):
try:
await future
finally:
- thread.join()
+ thread.join(timeout)
+
+ if thread.is_alive():
+ warnings.warn("The executor did not finishing joining "
+ f"its threads within {timeout} seconds.",
+ RuntimeWarning, stacklevel=2)
+ self._default_executor.shutdown(wait=False)
def _do_shutdown(self, future):
try:
@@ -992,7 +1023,8 @@ class BaseEventLoop(events.AbstractEventLoop):
local_addr=None, server_hostname=None,
ssl_handshake_timeout=None,
ssl_shutdown_timeout=None,
- happy_eyeballs_delay=None, interleave=None):
+ happy_eyeballs_delay=None, interleave=None,
+ all_errors=False):
"""Connect to a TCP server.
Create a streaming transport connection to a given internet host and
@@ -1082,6 +1114,8 @@ class BaseEventLoop(events.AbstractEventLoop):
if sock is None:
exceptions = [exc for sub in exceptions for exc in sub]
try:
+ if all_errors:
+ raise ExceptionGroup("create_connection failed", exceptions)
if len(exceptions) == 1:
raise exceptions[0]
else:
@@ -1819,7 +1853,22 @@ class BaseEventLoop(events.AbstractEventLoop):
exc_info=True)
else:
try:
- self._exception_handler(self, context)
+ ctx = None
+ thing = context.get("task")
+ if thing is None:
+ # Even though Futures don't have a context,
+ # Task is a subclass of Future,
+ # and sometimes the 'future' key holds a Task.
+ thing = context.get("future")
+ if thing is None:
+ # Handles also have a context.
+ thing = context.get("handle")
+ if thing is not None and hasattr(thing, "get_context"):
+ ctx = thing.get_context()
+ if ctx is not None and hasattr(ctx, "run"):
+ ctx.run(self._exception_handler, self, context)
+ else:
+ self._exception_handler(self, context)
except (SystemExit, KeyboardInterrupt):
raise
except BaseException as exc: