[3.13] gh-132106: Ensure that running `logging.handlers.QueueListener… (GH-132471)

Cherry-picked using 5863cd70b8
This commit is contained in:
Vinay Sajip 2025-04-13 13:00:50 +01:00 committed by GitHub
parent 4ff5d88fb1
commit 1dcdac6e08
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 21 additions and 6 deletions

View file

@ -1172,6 +1172,10 @@ possible, while any potentially slow operations (such as sending an email via
This starts up a background thread to monitor the queue for
LogRecords to process.
.. versionchanged:: next
Raises :exc:`RuntimeError` if called and the listener is already
running.
.. method:: stop()
Stops the listener.

View file

@ -1545,6 +1545,9 @@ class QueueListener(object):
This starts up a background thread to monitor the queue for
LogRecords to process.
"""
if self._thread is not None:
raise RuntimeError("Listener already started")
self._thread = t = threading.Thread(target=self._monitor)
t.daemon = True
t.start()

View file

@ -4300,8 +4300,6 @@ class QueueHandlerTest(BaseTest):
self.assertEqual(formatted_msg, log_record.msg)
self.assertEqual(formatted_msg, log_record.message)
@unittest.skipUnless(hasattr(logging.handlers, 'QueueListener'),
'logging.handlers.QueueListener required for this test')
def test_queue_listener(self):
handler = TestHandler(support.Matcher())
listener = logging.handlers.QueueListener(self.queue, handler)
@ -4336,8 +4334,18 @@ class QueueHandlerTest(BaseTest):
self.assertTrue(handler.matches(levelno=logging.CRITICAL, message='6'))
handler.close()
@unittest.skipUnless(hasattr(logging.handlers, 'QueueListener'),
'logging.handlers.QueueListener required for this test')
# doesn't hurt to call stop() more than once.
listener.stop()
self.assertIsNone(listener._thread)
def test_queue_listener_multi_start(self):
handler = TestHandler(support.Matcher())
listener = logging.handlers.QueueListener(self.queue, handler)
listener.start()
self.assertRaises(RuntimeError, listener.start)
listener.stop()
self.assertIsNone(listener._thread)
def test_queue_listener_with_StreamHandler(self):
# Test that traceback and stack-info only appends once (bpo-34334, bpo-46755).
listener = logging.handlers.QueueListener(self.queue, self.root_hdlr)
@ -4352,8 +4360,6 @@ class QueueHandlerTest(BaseTest):
self.assertEqual(self.stream.getvalue().strip().count('Traceback'), 1)
self.assertEqual(self.stream.getvalue().strip().count('Stack'), 1)
@unittest.skipUnless(hasattr(logging.handlers, 'QueueListener'),
'logging.handlers.QueueListener required for this test')
def test_queue_listener_with_multiple_handlers(self):
# Test that queue handler format doesn't affect other handler formats (bpo-35726).
self.que_hdlr.setFormatter(self.root_formatter)

View file

@ -0,0 +1,2 @@
:meth:`QueueListener.start <logging.handlers.QueueListener.start>` now
raises a :exc:`RuntimeError` if the listener is already started.