This commit is contained in:
ton
2024-10-07 10:13:40 +07:00
parent aa1631742f
commit 3a7d696db6
9729 changed files with 1832837 additions and 161742 deletions

View File

@@ -16,6 +16,7 @@ to modify the meaning of the API call itself.
import collections
import collections.abc
import concurrent.futures
import errno
import functools
import heapq
import itertools
@@ -44,6 +45,7 @@ from . import protocols
from . import sslproto
from . import staggered
from . import tasks
from . import timeouts
from . import transports
from . import trsock
from .log import logger
@@ -305,7 +307,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:
@@ -377,7 +379,27 @@ class Server(events.AbstractServer):
self._serving_forever_fut = None
async def wait_closed(self):
if self._waiters is None or self._active_count == 0:
"""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)
@@ -575,23 +597,24 @@ class BaseEventLoop(events.AbstractEventLoop):
thread = threading.Thread(target=self._do_shutdown, args=(future,))
thread.start()
try:
await future
finally:
thread.join(timeout)
if thread.is_alive():
async with timeouts.timeout(timeout):
await future
except TimeoutError:
warnings.warn("The executor did not finishing joining "
f"its threads within {timeout} seconds.",
RuntimeWarning, stacklevel=2)
f"its threads within {timeout} seconds.",
RuntimeWarning, stacklevel=2)
self._default_executor.shutdown(wait=False)
else:
thread.join()
def _do_shutdown(self, future):
try:
self._default_executor.shutdown(wait=True)
if not self.is_closed():
self.call_soon_threadsafe(future.set_result, None)
self.call_soon_threadsafe(futures._set_result_unless_cancelled,
future, None)
except Exception as ex:
if not self.is_closed():
if not self.is_closed() and not future.cancelled():
self.call_soon_threadsafe(future.set_exception, ex)
def _check_running(self):
@@ -971,8 +994,7 @@ class BaseEventLoop(events.AbstractEventLoop):
except OSError as exc:
msg = (
f'error while attempting to bind on '
f'address {laddr!r}: '
f'{exc.strerror.lower()}'
f'address {laddr!r}: {str(exc).lower()}'
)
exc = OSError(exc.errno, msg)
my_exceptions.append(exc)
@@ -1294,9 +1316,9 @@ class BaseEventLoop(events.AbstractEventLoop):
allow_broadcast=None, sock=None):
"""Create datagram connection."""
if sock is not None:
if sock.type != socket.SOCK_DGRAM:
if sock.type == socket.SOCK_STREAM:
raise ValueError(
f'A UDP Socket was expected, got {sock!r}')
f'A datagram socket was expected, got {sock!r}')
if (local_addr or remote_addr or
family or proto or flags or
reuse_port or allow_broadcast):
@@ -1536,9 +1558,22 @@ class BaseEventLoop(events.AbstractEventLoop):
try:
sock.bind(sa)
except OSError as err:
raise OSError(err.errno, 'error while attempting '
'to bind on address %r: %s'
% (sa, err.strerror.lower())) from None
msg = ('error while attempting '
'to bind on address %r: %s'
% (sa, str(err).lower()))
if err.errno == errno.EADDRNOTAVAIL:
# Assume the family is not enabled (bpo-30945)
sockets.pop()
sock.close()
if self._debug:
logger.warning(msg)
continue
raise OSError(err.errno, msg) from None
if not sockets:
raise OSError('could not bind on any address out of %r'
% ([info[4] for info in infos],))
completed = True
finally:
if not completed: