summaryrefslogtreecommitdiffstats
path: root/Lib/asyncio/base_events.py
diff options
context:
space:
mode:
authorDong Uk, Kang <nailbrainz@gmail.com>2022-11-22 15:06:20 (GMT)
committerGitHub <noreply@github.com>2022-11-22 15:06:20 (GMT)
commit995f6170c78570eca818f7e7dbd8a7661c171a81 (patch)
treefdfaf448f9fb3bf4a601c1cb51c001deab62ea01 /Lib/asyncio/base_events.py
parent9a91182d4a87e4511dad20ad101e3eab0e1c5088 (diff)
downloadcpython-995f6170c78570eca818f7e7dbd8a7661c171a81.zip
cpython-995f6170c78570eca818f7e7dbd8a7661c171a81.tar.gz
cpython-995f6170c78570eca818f7e7dbd8a7661c171a81.tar.bz2
gh-88863: Clear ref cycles to resolve leak when asyncio.open_connection raises (#95739)
Break reference cycles to resolve memory leak, by removing local exception and future instances from the frame
Diffstat (limited to 'Lib/asyncio/base_events.py')
-rw-r--r--Lib/asyncio/base_events.py31
1 files changed, 19 insertions, 12 deletions
diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py
index c8a2f9f..91d32e3 100644
--- a/Lib/asyncio/base_events.py
+++ b/Lib/asyncio/base_events.py
@@ -986,6 +986,8 @@ class BaseEventLoop(events.AbstractEventLoop):
if sock is not None:
sock.close()
raise
+ finally:
+ exceptions = my_exceptions = None
async def create_connection(
self, protocol_factory, host=None, port=None,
@@ -1084,19 +1086,22 @@ class BaseEventLoop(events.AbstractEventLoop):
if sock is None:
exceptions = [exc for sub in exceptions for exc in sub]
- if all_errors:
- raise ExceptionGroup("create_connection failed", exceptions)
- if len(exceptions) == 1:
- raise exceptions[0]
- else:
- # If they all have the same str(), raise one.
- model = str(exceptions[0])
- if all(str(exc) == model for exc in exceptions):
+ try:
+ if all_errors:
+ raise ExceptionGroup("create_connection failed", exceptions)
+ if len(exceptions) == 1:
raise exceptions[0]
- # Raise a combined exception so the user can see all
- # the various error messages.
- raise OSError('Multiple exceptions: {}'.format(
- ', '.join(str(exc) for exc in exceptions)))
+ else:
+ # If they all have the same str(), raise one.
+ model = str(exceptions[0])
+ if all(str(exc) == model for exc in exceptions):
+ raise exceptions[0]
+ # Raise a combined exception so the user can see all
+ # the various error messages.
+ raise OSError('Multiple exceptions: {}'.format(
+ ', '.join(str(exc) for exc in exceptions)))
+ finally:
+ exceptions = None
else:
if sock is None:
@@ -1904,6 +1909,8 @@ class BaseEventLoop(events.AbstractEventLoop):
event_list = self._selector.select(timeout)
self._process_events(event_list)
+ # Needed to break cycles when an exception occurs.
+ event_list = None
# Handle 'later' callbacks that are ready.
end_time = self.time() + self._clock_resolution