]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-132106: Ensure that running `logging.handlers.QueueListener… (GH-132471)
authorVinay Sajip <vinay_sajip@yahoo.co.uk>
Sun, 13 Apr 2025 12:00:50 +0000 (13:00 +0100)
committerGitHub <noreply@github.com>
Sun, 13 Apr 2025 12:00:50 +0000 (13:00 +0100)
Cherry-picked using 5863cd70b8782313b52bb8c71a4127d7ea4c50e9

Doc/library/logging.handlers.rst
Lib/logging/handlers.py
Lib/test/test_logging.py
Misc/NEWS.d/next/Library/2025-04-12-09-30-24.gh-issue-132106.OxUds3.rst [new file with mode: 0644]

index 5a081f9e7add996c094b7a1528097d61ca2bdc56..e63c253e123552b297995c35e109f4ca500483ab 100644 (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.
index da9c59c119f3db36e765454ceccd0df535ebc8b5..d3ea06c731ef89366d5d8385c01b72bee029f734 100644 (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()
index 678c23dad67faae1791bb9dbc2154a4ecaaaea6b..58e0381c4aa93474ed0c63a8ef54067984e2f534 100644 (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)
diff --git a/Misc/NEWS.d/next/Library/2025-04-12-09-30-24.gh-issue-132106.OxUds3.rst b/Misc/NEWS.d/next/Library/2025-04-12-09-30-24.gh-issue-132106.OxUds3.rst
new file mode 100644 (file)
index 0000000..b6d58a2
--- /dev/null
@@ -0,0 +1,2 @@
+:meth:`QueueListener.start <logging.handlers.QueueListener.start>` now\r
+raises a :exc:`RuntimeError` if the listener is already started.\r