Calling asyncio.Future.set_exception() or asyncio.Future.set_result()
more than once for a given Future object raises an
asyncio.InvalidStateError exception.
In the case of AsyncServer:
- it is enough to capture the first exception raised by higher-level
logic as no exceptions at all are expected to be raised in the first
place,
- no distinction is made between SIGINT and SIGTERM; the only purpose
of the signal handler is to make the server exit cleanly.
Given the above, make both AsyncServer._handle_exception() and
AsyncServer._signal_done() idempotent by ignoring
asyncio.InvalidStateError exceptions raised by the relevant
asyncio.Future.set_*() calls.
) -> None:
assert self._work_done
exception = context.get("exception", RuntimeError(context["message"]))
- self._work_done.set_exception(exception)
+ try:
+ self._work_done.set_exception(exception)
+ except asyncio.InvalidStateError:
+ pass
def _setup_signals(self) -> None:
loop = self._get_asyncio_loop()
def _signal_done(self) -> None:
assert self._work_done
- self._work_done.set_result(True)
+ try:
+ self._work_done.set_result(True)
+ except asyncio.InvalidStateError:
+ pass
async def _listen_udp(self) -> None:
if not self._udp_handler: