summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurie O <laurie_opperman@hotmail.com>2024-04-10 15:01:42 (GMT)
committerGitHub <noreply@github.com>2024-04-10 15:01:42 (GMT)
commit6bc0b33a91713ee62fd1860d28b19cb620c45971 (patch)
treeebaa3fd16dace275dbc35702def073536ee230f0
parentdfcae4379f2cc4d352a180f9fef2381570aa9bcb (diff)
downloadcpython-6bc0b33a91713ee62fd1860d28b19cb620c45971.zip
cpython-6bc0b33a91713ee62fd1860d28b19cb620c45971.tar.gz
cpython-6bc0b33a91713ee62fd1860d28b19cb620c45971.tar.bz2
gh-117531: Unblock getters after non-immediate queue shutdown (#117532)
(This is a small tweak of the original gh-104750 which added shutdown.)
-rw-r--r--Doc/library/queue.rst6
-rw-r--r--Lib/queue.py8
-rw-r--r--Lib/test/test_queue.py17
3 files changed, 26 insertions, 5 deletions
diff --git a/Doc/library/queue.rst b/Doc/library/queue.rst
index f2a6dbf..fce2331 100644
--- a/Doc/library/queue.rst
+++ b/Doc/library/queue.rst
@@ -245,8 +245,10 @@ them down.
queue is empty. Set *immediate* to true to make :meth:`~Queue.get` raise
immediately instead.
- All blocked callers of :meth:`~Queue.put` will be unblocked. If *immediate*
- is true, also unblock callers of :meth:`~Queue.get` and :meth:`~Queue.join`.
+ All blocked callers of :meth:`~Queue.put` and :meth:`~Queue.get` will be
+ unblocked. If *immediate* is true, a task will be marked as done for each
+ remaining item in the queue, which may unblock callers of
+ :meth:`~Queue.join`.
.. versionadded:: 3.13
diff --git a/Lib/queue.py b/Lib/queue.py
index 387ce54..25beb46 100644
--- a/Lib/queue.py
+++ b/Lib/queue.py
@@ -239,8 +239,9 @@ class Queue:
By default, gets will only raise once the queue is empty. Set
'immediate' to True to make gets raise immediately instead.
- All blocked callers of put() will be unblocked, and also get()
- and join() if 'immediate'.
+ All blocked callers of put() and get() will be unblocked. If
+ 'immediate', a task is marked as done for each item remaining in
+ the queue, which may unblock callers of join().
'''
with self.mutex:
self.is_shutdown = True
@@ -249,9 +250,10 @@ class Queue:
self._get()
if self.unfinished_tasks > 0:
self.unfinished_tasks -= 1
- self.not_empty.notify_all()
# release all blocked threads in `join()`
self.all_tasks_done.notify_all()
+ # All getters need to re-check queue-empty to raise ShutDown
+ self.not_empty.notify_all()
self.not_full.notify_all()
# Override these methods to implement other queue organizations
diff --git a/Lib/test/test_queue.py b/Lib/test/test_queue.py
index c4d1011..d5927fb 100644
--- a/Lib/test/test_queue.py
+++ b/Lib/test/test_queue.py
@@ -636,6 +636,23 @@ class BaseQueueTestMixin(BlockingTestMixin):
self.assertEqual(results, [True]*len(thrds))
+ def test_shutdown_pending_get(self):
+ def get():
+ try:
+ results.append(q.get())
+ except Exception as e:
+ results.append(e)
+
+ q = self.type2test()
+ results = []
+ get_thread = threading.Thread(target=get)
+ get_thread.start()
+ q.shutdown(immediate=False)
+ get_thread.join(timeout=10.0)
+ self.assertFalse(get_thread.is_alive())
+ self.assertEqual(len(results), 1)
+ self.assertIsInstance(results[0], self.queue.ShutDown)
+
class QueueTest(BaseQueueTestMixin):