Skip to content

Commit 863c0a3

Browse files
miss-islingtonpicnixzgpshead
authored
[3.12] gh-120012: clarify the behaviour of multiprocessing.Queue.empty on closed queues. (GH-120102) (#120470)
Co-authored-by: Bénédikt Tran <[email protected]> Co-authored-by: Gregory P. Smith <[email protected]>
1 parent 98340a0 commit 863c0a3

File tree

3 files changed

+33
-0
lines changed

3 files changed

+33
-0
lines changed

Doc/library/multiprocessing.rst

+4
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,8 @@ For an example of the usage of queues for interprocess communication see
847847
Return ``True`` if the queue is empty, ``False`` otherwise. Because of
848848
multithreading/multiprocessing semantics, this is not reliable.
849849

850+
May raise an :exc:`OSError` on closed queues. (not guaranteed)
851+
850852
.. method:: full()
851853

852854
Return ``True`` if the queue is full, ``False`` otherwise. Because of
@@ -950,6 +952,8 @@ For an example of the usage of queues for interprocess communication see
950952

951953
Return ``True`` if the queue is empty, ``False`` otherwise.
952954

955+
Always raises an :exc:`OSError` if the SimpleQueue is closed.
956+
953957
.. method:: get()
954958

955959
Remove and return an item from the queue.

Lib/test/_test_multiprocessing.py

+26
Original file line numberDiff line numberDiff line change
@@ -1332,6 +1332,23 @@ def _on_queue_feeder_error(e, obj):
13321332
self.assertTrue(not_serializable_obj.reduce_was_called)
13331333
self.assertTrue(not_serializable_obj.on_queue_feeder_error_was_called)
13341334

1335+
def test_closed_queue_empty_exceptions(self):
1336+
# Assert that checking the emptiness of an unused closed queue
1337+
# does not raise an OSError. The rationale is that q.close() is
1338+
# a no-op upon construction and becomes effective once the queue
1339+
# has been used (e.g., by calling q.put()).
1340+
for q in multiprocessing.Queue(), multiprocessing.JoinableQueue():
1341+
q.close() # this is a no-op since the feeder thread is None
1342+
q.join_thread() # this is also a no-op
1343+
self.assertTrue(q.empty())
1344+
1345+
for q in multiprocessing.Queue(), multiprocessing.JoinableQueue():
1346+
q.put('foo') # make sure that the queue is 'used'
1347+
q.close() # close the feeder thread
1348+
q.join_thread() # make sure to join the feeder thread
1349+
with self.assertRaisesRegex(OSError, 'is closed'):
1350+
q.empty()
1351+
13351352
def test_closed_queue_put_get_exceptions(self):
13361353
for q in multiprocessing.Queue(), multiprocessing.JoinableQueue():
13371354
q.close()
@@ -5691,6 +5708,15 @@ def _test_empty(cls, queue, child_can_start, parent_can_continue):
56915708
finally:
56925709
parent_can_continue.set()
56935710

5711+
def test_empty_exceptions(self):
5712+
# Assert that checking emptiness of a closed queue raises
5713+
# an OSError, independently of whether the queue was used
5714+
# or not. This differs from Queue and JoinableQueue.
5715+
q = multiprocessing.SimpleQueue()
5716+
q.close() # close the pipe
5717+
with self.assertRaisesRegex(OSError, 'is closed'):
5718+
q.empty()
5719+
56945720
def test_empty(self):
56955721
queue = multiprocessing.SimpleQueue()
56965722
child_can_start = multiprocessing.Event()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Clarify the behaviours of :meth:`multiprocessing.Queue.empty` and
2+
:meth:`multiprocessing.SimpleQueue.empty` on closed queues.
3+
Patch by Bénédikt Tran.

0 commit comments

Comments
 (0)