diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2022-02-03 15:42:28 +0000 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2022-02-03 15:42:28 +0000 |
| commit | 31f59af395922b7f40799e75db6e15ff52d8f94a (patch) | |
| tree | 3dad1f53308b49c39d898334ff59d3cea58d3855 /python/qemu/aqmp/protocol.py | |
| parent | 8f3e5ce773c62bb5c4a847f3a9a5c98bbb3b359f (diff) | |
| parent | b0b662bb2b340d63529672b5bdae596a6243c4d0 (diff) | |
| download | focaccia-qemu-31f59af395922b7f40799e75db6e15ff52d8f94a.tar.gz focaccia-qemu-31f59af395922b7f40799e75db6e15ff52d8f94a.zip | |
Merge remote-tracking branch 'remotes/jsnow-gitlab/tags/python-pull-request' into staging
Python patches Peter: I expect this to address the iotest 040,041 failures you observed on NetBSD. If it doesn't, let me know. # gpg: Signature made Thu 03 Feb 2022 01:59:32 GMT # gpg: using RSA key F9B7ABDBBCACDF95BE76CBD07DEF8106AAFC390E # gpg: Good signature from "John Snow (John Huston) <jsnow@redhat.com>" [full] # Primary key fingerprint: FAEB 9711 A12C F475 812F 18F2 88A9 064D 1835 61EB # Subkey fingerprint: F9B7 ABDB BCAC DF95 BE76 CBD0 7DEF 8106 AAFC 390E * remotes/jsnow-gitlab/tags/python-pull-request: python/aqmp: add socket bind step to legacy.py python: upgrade mypy to 0.780 python/machine: raise VMLaunchFailure exception from launch() python/aqmp: Fix negotiation with pre-"oob" QEMU Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'python/qemu/aqmp/protocol.py')
| -rw-r--r-- | python/qemu/aqmp/protocol.py | 41 |
1 files changed, 38 insertions, 3 deletions
diff --git a/python/qemu/aqmp/protocol.py b/python/qemu/aqmp/protocol.py index 50e973c2f2..33358f5cd7 100644 --- a/python/qemu/aqmp/protocol.py +++ b/python/qemu/aqmp/protocol.py @@ -15,6 +15,7 @@ from asyncio import StreamReader, StreamWriter from enum import Enum from functools import wraps import logging +import socket from ssl import SSLContext from typing import ( Any, @@ -238,6 +239,9 @@ class AsyncProtocol(Generic[T]): self._runstate = Runstate.IDLE self._runstate_changed: Optional[asyncio.Event] = None + # Workaround for bind() + self._sock: Optional[socket.socket] = None + def __repr__(self) -> str: cls_name = type(self).__name__ tokens = [] @@ -427,6 +431,34 @@ class AsyncProtocol(Generic[T]): else: await self._do_connect(address, ssl) + def _bind_hack(self, address: Union[str, Tuple[str, int]]) -> None: + """ + Used to create a socket in advance of accept(). + + This is a workaround to ensure that we can guarantee timing of + precisely when a socket exists to avoid a connection attempt + bouncing off of nothing. + + Python 3.7+ adds a feature to separate the server creation and + listening phases instead, and should be used instead of this + hack. + """ + if isinstance(address, tuple): + family = socket.AF_INET + else: + family = socket.AF_UNIX + + sock = socket.socket(family, socket.SOCK_STREAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + + try: + sock.bind(address) + except: + sock.close() + raise + + self._sock = sock + @upper_half async def _do_accept(self, address: SocketAddrT, ssl: Optional[SSLContext] = None) -> None: @@ -464,24 +496,27 @@ class AsyncProtocol(Generic[T]): if isinstance(address, tuple): coro = asyncio.start_server( _client_connected_cb, - host=address[0], - port=address[1], + host=None if self._sock else address[0], + port=None if self._sock else address[1], ssl=ssl, backlog=1, limit=self._limit, + sock=self._sock, ) else: coro = asyncio.start_unix_server( _client_connected_cb, - path=address, + path=None if self._sock else address, ssl=ssl, backlog=1, limit=self._limit, + sock=self._sock, ) server = await coro # Starts listening await connected.wait() # Waits for the callback to fire (and finish) assert server is None + self._sock = None self.logger.debug("Connection accepted.") |