From: Michał Kępień Date: Sun, 21 Dec 2025 05:25:56 +0000 (+0100) Subject: Make exception/signal handlers idempotent X-Git-Tag: v9.21.17~17^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0ec94e501a04dc6a0730d75e6eeab2782202e16b;p=thirdparty%2Fbind9.git Make exception/signal handlers idempotent 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. --- diff --git a/bin/tests/system/isctest/asyncserver.py b/bin/tests/system/isctest/asyncserver.py index 98fec6b6634..6ec3b00f10d 100644 --- a/bin/tests/system/isctest/asyncserver.py +++ b/bin/tests/system/isctest/asyncserver.py @@ -198,7 +198,10 @@ class AsyncServer: ) -> 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() @@ -207,7 +210,10 @@ class AsyncServer: 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: