From c3b317762981baf203b2118a10f379505f3528b6 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 22 Aug 2017 12:37:23 +0200 Subject: [PATCH 1/3] bpo-31249: Fix ref cycle in ThreadPoolExecutor concurrent.futures: WorkItem.run() used by ThreadPoolExecutor now breaks a reference cycle between an exception object and the WorkItem object. ThreadPoolExecutor.shutdown() now also clears its threads set. --- Lib/concurrent/futures/thread.py | 7 +++++-- .../next/Library/2017-08-22-12-44-48.bpo-31249.STPbb9.rst | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2017-08-22-12-44-48.bpo-31249.STPbb9.rst diff --git a/Lib/concurrent/futures/thread.py b/Lib/concurrent/futures/thread.py index 1f0a1d4b977f316..ca579af75d549b9 100644 --- a/Lib/concurrent/futures/thread.py +++ b/Lib/concurrent/futures/thread.py @@ -54,8 +54,10 @@ def run(self): try: result = self.fn(*self.args, **self.kwargs) - except BaseException as e: - self.future.set_exception(e) + except BaseException as exc: + self.future.set_exception(exc) + # Break a reference cycle with the exception 'exc' + self = None else: self.future.set_result(result) @@ -148,4 +150,5 @@ def shutdown(self, wait=True): if wait: for t in self._threads: t.join() + self._threads.clear() shutdown.__doc__ = _base.Executor.shutdown.__doc__ diff --git a/Misc/NEWS.d/next/Library/2017-08-22-12-44-48.bpo-31249.STPbb9.rst b/Misc/NEWS.d/next/Library/2017-08-22-12-44-48.bpo-31249.STPbb9.rst new file mode 100644 index 000000000000000..d3dbc124b606b24 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-08-22-12-44-48.bpo-31249.STPbb9.rst @@ -0,0 +1,3 @@ +concurrent.futures: WorkItem.run() used by ThreadPoolExecutor now breaks a +reference cycle between an exception object and the WorkItem object. +ThreadPoolExecutor.shutdown() now also clears its threads set. From 7e5abd2a882f1fa7b8084741dacd4fc1ce8f7969 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 22 Aug 2017 15:52:32 +0200 Subject: [PATCH 2/3] shutdown() now only clears threads if wait is true. --- Lib/concurrent/futures/thread.py | 2 +- .../next/Library/2017-08-22-12-44-48.bpo-31249.STPbb9.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/concurrent/futures/thread.py b/Lib/concurrent/futures/thread.py index ca579af75d549b9..320b2731b35f870 100644 --- a/Lib/concurrent/futures/thread.py +++ b/Lib/concurrent/futures/thread.py @@ -150,5 +150,5 @@ def shutdown(self, wait=True): if wait: for t in self._threads: t.join() - self._threads.clear() + self._threads.clear() shutdown.__doc__ = _base.Executor.shutdown.__doc__ diff --git a/Misc/NEWS.d/next/Library/2017-08-22-12-44-48.bpo-31249.STPbb9.rst b/Misc/NEWS.d/next/Library/2017-08-22-12-44-48.bpo-31249.STPbb9.rst index d3dbc124b606b24..2e808348986a12a 100644 --- a/Misc/NEWS.d/next/Library/2017-08-22-12-44-48.bpo-31249.STPbb9.rst +++ b/Misc/NEWS.d/next/Library/2017-08-22-12-44-48.bpo-31249.STPbb9.rst @@ -1,3 +1,3 @@ concurrent.futures: WorkItem.run() used by ThreadPoolExecutor now breaks a reference cycle between an exception object and the WorkItem object. -ThreadPoolExecutor.shutdown() now also clears its threads set. +ThreadPoolExecutor.shutdown(wait=True) now also clears its threads set. From b32a53f1e9272654e38756977326f06a6f848872 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 22 Aug 2017 15:56:52 +0200 Subject: [PATCH 3/3] Revert changes on shutdown() --- Lib/concurrent/futures/thread.py | 1 - .../NEWS.d/next/Library/2017-08-22-12-44-48.bpo-31249.STPbb9.rst | 1 - 2 files changed, 2 deletions(-) diff --git a/Lib/concurrent/futures/thread.py b/Lib/concurrent/futures/thread.py index 320b2731b35f870..0b5d5373ffdc0aa 100644 --- a/Lib/concurrent/futures/thread.py +++ b/Lib/concurrent/futures/thread.py @@ -150,5 +150,4 @@ def shutdown(self, wait=True): if wait: for t in self._threads: t.join() - self._threads.clear() shutdown.__doc__ = _base.Executor.shutdown.__doc__ diff --git a/Misc/NEWS.d/next/Library/2017-08-22-12-44-48.bpo-31249.STPbb9.rst b/Misc/NEWS.d/next/Library/2017-08-22-12-44-48.bpo-31249.STPbb9.rst index 2e808348986a12a..f11a66802d1bc14 100644 --- a/Misc/NEWS.d/next/Library/2017-08-22-12-44-48.bpo-31249.STPbb9.rst +++ b/Misc/NEWS.d/next/Library/2017-08-22-12-44-48.bpo-31249.STPbb9.rst @@ -1,3 +1,2 @@ concurrent.futures: WorkItem.run() used by ThreadPoolExecutor now breaks a reference cycle between an exception object and the WorkItem object. -ThreadPoolExecutor.shutdown(wait=True) now also clears its threads set.