@@ -1332,6 +1332,23 @@ def _on_queue_feeder_error(e, obj):
1332
1332
self .assertTrue (not_serializable_obj .reduce_was_called )
1333
1333
self .assertTrue (not_serializable_obj .on_queue_feeder_error_was_called )
1334
1334
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
+
1335
1352
def test_closed_queue_put_get_exceptions (self ):
1336
1353
for q in multiprocessing .Queue (), multiprocessing .JoinableQueue ():
1337
1354
q .close ()
@@ -5815,6 +5832,15 @@ def _test_empty(cls, queue, child_can_start, parent_can_continue):
5815
5832
finally :
5816
5833
parent_can_continue .set ()
5817
5834
5835
+ def test_empty_exceptions (self ):
5836
+ # Assert that checking emptiness of a closed queue raises
5837
+ # an OSError, independently of whether the queue was used
5838
+ # or not. This differs from Queue and JoinableQueue.
5839
+ q = multiprocessing .SimpleQueue ()
5840
+ q .close () # close the pipe
5841
+ with self .assertRaisesRegex (OSError , 'is closed' ):
5842
+ q .empty ()
5843
+
5818
5844
def test_empty (self ):
5819
5845
queue = multiprocessing .SimpleQueue ()
5820
5846
child_can_start = multiprocessing .Event ()
0 commit comments