diff options
author | David Robertson <davidr@element.io> | 2022-10-06 19:17:50 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-06 18:17:50 +0000 |
commit | cb20b885cb4bd1648581dd043a184d86fc8c7a00 (patch) | |
tree | 20ffd08e96133128eb1c363fc00bc5379642ed3c /synapse/federation/transport/client.py | |
parent | Merge tag 'v1.69.0rc2' into develop (diff) | |
download | synapse-cb20b885cb4bd1648581dd043a184d86fc8c7a00.tar.xz |
Always close _all_ `ijson` coroutines, even if doing so raises Exceptions (#14065)
Diffstat (limited to 'synapse/federation/transport/client.py')
-rw-r--r-- | synapse/federation/transport/client.py | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/synapse/federation/transport/client.py b/synapse/federation/transport/client.py index 32074b8ca6..cd39d4d111 100644 --- a/synapse/federation/transport/client.py +++ b/synapse/federation/transport/client.py @@ -45,6 +45,7 @@ from synapse.federation.units import Transaction from synapse.http.matrixfederationclient import ByteParser from synapse.http.types import QueryParams from synapse.types import JsonDict +from synapse.util import ExceptionBundle logger = logging.getLogger(__name__) @@ -926,8 +927,7 @@ class SendJoinParser(ByteParser[SendJoinResponse]): return len(data) def finish(self) -> SendJoinResponse: - for c in self._coros: - c.close() + _close_coros(self._coros) if self._response.event_dict: self._response.event = make_event_from_dict( @@ -970,6 +970,27 @@ class _StateParser(ByteParser[StateRequestResponse]): return len(data) def finish(self) -> StateRequestResponse: - for c in self._coros: - c.close() + _close_coros(self._coros) return self._response + + +def _close_coros(coros: Iterable[Generator[None, bytes, None]]) -> None: + """Close each of the given coroutines. + + Always calls .close() on each coroutine, even if doing so raises an exception. + Any exceptions raised are aggregated into an ExceptionBundle. + + :raises ExceptionBundle: if at least one coroutine fails to close. + """ + exceptions = [] + for c in coros: + try: + c.close() + except Exception as e: + exceptions.append(e) + + if exceptions: + # raise from the first exception so that the traceback has slightly more context + raise ExceptionBundle( + f"There were {len(exceptions)} errors closing coroutines", exceptions + ) from exceptions[0] |