Skip to content

Commit dae1963

Browse files
miss-islingtonjcea
andauthored
bpo-35930: Raising an exception raised in a "future" instance will create reference cycles (GH-24995) (#25071)
Before: https://lists.es.python.org/pipermail/general/attachments/20201229/0c14bc58/attachment-0002.png After: https://lists.es.python.org/pipermail/general/attachments/20201229/0c14bc58/attachment-0003.png (cherry picked from commit 32430aa) Co-authored-by: Jesús Cea <jcea@jcea.es> Co-authored-by: Jesús Cea <jcea@jcea.es>
1 parent 7e38d33 commit dae1963

File tree

2 files changed

+25
-15
lines changed

2 files changed

+25
-15
lines changed

Lib/concurrent/futures/_base.py

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,11 @@ def done(self):
385385

386386
def __get_result(self):
387387
if self._exception:
388-
raise self._exception
388+
try:
389+
raise self._exception
390+
finally:
391+
# Break a reference cycle with the exception in self._exception
392+
self = None
389393
else:
390394
return self._result
391395

@@ -425,20 +429,24 @@ def result(self, timeout=None):
425429
timeout.
426430
Exception: If the call raised then that exception will be raised.
427431
"""
428-
with self._condition:
429-
if self._state in [CANCELLED, CANCELLED_AND_NOTIFIED]:
430-
raise CancelledError()
431-
elif self._state == FINISHED:
432-
return self.__get_result()
433-
434-
self._condition.wait(timeout)
435-
436-
if self._state in [CANCELLED, CANCELLED_AND_NOTIFIED]:
437-
raise CancelledError()
438-
elif self._state == FINISHED:
439-
return self.__get_result()
440-
else:
441-
raise TimeoutError()
432+
try:
433+
with self._condition:
434+
if self._state in [CANCELLED, CANCELLED_AND_NOTIFIED]:
435+
raise CancelledError()
436+
elif self._state == FINISHED:
437+
return self.__get_result()
438+
439+
self._condition.wait(timeout)
440+
441+
if self._state in [CANCELLED, CANCELLED_AND_NOTIFIED]:
442+
raise CancelledError()
443+
elif self._state == FINISHED:
444+
return self.__get_result()
445+
else:
446+
raise TimeoutError()
447+
finally:
448+
# Break a reference cycle with the exception in self._exception
449+
self = None
442450

443451
def exception(self, timeout=None):
444452
"""Return the exception raised by the call that the future represents.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Raising an exception raised in a "future" instance will create reference
2+
cycles.

0 commit comments

Comments
 (0)