Kaydet (Commit) 6b973747 authored tarafından Andrew Svetlov's avatar Andrew Svetlov

Issue #16284: Prevent keeping unnecessary references to worker functions in…

Issue #16284: Prevent keeping unnecessary references to worker functions in concurrent.futures ThreadPoolExecutor.
üst 0f77bf27
...@@ -240,6 +240,8 @@ def _queue_management_worker(executor_reference, ...@@ -240,6 +240,8 @@ def _queue_management_worker(executor_reference,
"terminated abruptly while the future was " "terminated abruptly while the future was "
"running or pending." "running or pending."
)) ))
# Delete references to object. See issue16284
del work_item
pending_work_items.clear() pending_work_items.clear()
# Terminate remaining workers forcibly: the queues or their # Terminate remaining workers forcibly: the queues or their
# locks may be in a dirty state and block forever. # locks may be in a dirty state and block forever.
...@@ -264,6 +266,8 @@ def _queue_management_worker(executor_reference, ...@@ -264,6 +266,8 @@ def _queue_management_worker(executor_reference,
work_item.future.set_exception(result_item.exception) work_item.future.set_exception(result_item.exception)
else: else:
work_item.future.set_result(result_item.result) work_item.future.set_result(result_item.result)
# Delete references to object. See issue16284
del work_item
# Check whether we should start shutting down. # Check whether we should start shutting down.
executor = executor_reference() executor = executor_reference()
# No more work items can be added if: # No more work items can be added if:
......
...@@ -63,6 +63,8 @@ def _worker(executor_reference, work_queue): ...@@ -63,6 +63,8 @@ def _worker(executor_reference, work_queue):
work_item = work_queue.get(block=True) work_item = work_queue.get(block=True)
if work_item is not None: if work_item is not None:
work_item.run() work_item.run()
# Delete references to object. See issue16284
del work_item
continue continue
executor = executor_reference() executor = executor_reference()
# Exit if: # Exit if:
......
...@@ -243,10 +243,14 @@ class Queue(object): ...@@ -243,10 +243,14 @@ class Queue(object):
if wacquire is None: if wacquire is None:
send(obj) send(obj)
# Delete references to object. See issue16284
del obj
else: else:
wacquire() wacquire()
try: try:
send(obj) send(obj)
# Delete references to object. See issue16284
del obj
finally: finally:
wrelease() wrelease()
except IndexError: except IndexError:
......
...@@ -15,6 +15,7 @@ import sys ...@@ -15,6 +15,7 @@ import sys
import threading import threading
import time import time
import unittest import unittest
import weakref
from concurrent import futures from concurrent import futures
from concurrent.futures._base import ( from concurrent.futures._base import (
...@@ -52,6 +53,11 @@ def sleep_and_print(t, msg): ...@@ -52,6 +53,11 @@ def sleep_and_print(t, msg):
sys.stdout.flush() sys.stdout.flush()
class MyObject(object):
def my_method(self):
pass
class ExecutorMixin: class ExecutorMixin:
worker_count = 5 worker_count = 5
...@@ -396,6 +402,22 @@ class ExecutorTest(unittest.TestCase): ...@@ -396,6 +402,22 @@ class ExecutorTest(unittest.TestCase):
self.executor.map(str, [2] * (self.worker_count + 1)) self.executor.map(str, [2] * (self.worker_count + 1))
self.executor.shutdown() self.executor.shutdown()
@test.support.cpython_only
def test_no_stale_references(self):
# Issue #16284: check that the executors don't unnecessarily hang onto
# references.
my_object = MyObject()
my_object_collected = threading.Event()
my_object_callback = weakref.ref(
my_object, lambda obj: my_object_collected.set())
# Deliberately discarding the future.
self.executor.submit(my_object.my_method)
del my_object
collected = my_object_collected.wait(timeout=5.0)
self.assertTrue(collected,
"Stale reference not collected within timeout.")
class ThreadPoolExecutorTest(ThreadPoolMixin, ExecutorTest): class ThreadPoolExecutorTest(ThreadPoolMixin, ExecutorTest):
def test_map_submits_without_iteration(self): def test_map_submits_without_iteration(self):
......
...@@ -726,6 +726,7 @@ Lukas Lueg ...@@ -726,6 +726,7 @@ Lukas Lueg
Loren Luke Loren Luke
Fredrik Lundh Fredrik Lundh
Mark Lutz Mark Lutz
Taras Lyapun
Jim Lynch Jim Lynch
Mikael Lyngvig Mikael Lyngvig
Martin von Löwis Martin von Löwis
......
...@@ -88,6 +88,9 @@ Core and Builtins ...@@ -88,6 +88,9 @@ Core and Builtins
Library Library
------- -------
- Issue #16284: Prevent keeping unnecessary references to worker functions
in concurrent.futures ThreadPoolExecutor.
- Issue #1207589: Add Cut/Copy/Paste items to IDLE right click Context Menu - Issue #1207589: Add Cut/Copy/Paste items to IDLE right click Context Menu
Patch by Todd Rovito. Patch by Todd Rovito.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment