]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-132106: Ensure that running `logging.handlers.QueueListener` cannot be started...
authorCharles Machalow <csm10495@gmail.com>
Sun, 13 Apr 2025 07:53:13 +0000 (00:53 -0700)
committerGitHub <noreply@github.com>
Sun, 13 Apr 2025 07:53:13 +0000 (08:53 +0100)
Prevents a thread leak
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Doc/library/logging.handlers.rst
Doc/whatsnew/3.14.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 b737fe311dfb6edc2ae2bc14c9dfb5a28a204105..72312b512a5884ca977fa1c2d70210120d5645ee 100644 (file)
@@ -1186,6 +1186,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 762d53eeb2df1a05c07c82916b7198a1a3ae1db6..421d12660b79568724dd24afe69a2fb67bb653b7 100644 (file)
@@ -819,6 +819,10 @@ logging.handlers
   manager protocol, allowing it to be used in a :keyword:`with` statement.
   (Contributed by Charles Machalow in :gh:`132106`.)
 
+* :meth:`QueueListener.start <logging.handlers.QueueListener.start>` now
+  raises a :exc:`RuntimeError` if the listener is already started.
+  (Contributed by Charles Machalow in :gh:`132106`.)
+
 
 mimetypes
 ---------
index 0571ed2356345abb427763a83039ebaff4e12621..2748b5941eade2ee56c5d1ade261702271af8704 100644 (file)
@@ -1561,6 +1561,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 11f6b64abe28fb280067e3c66bac678025d21ce1..9305844829a50052a376deb290aea5eb061ee25c 100644 (file)
@@ -4356,6 +4356,17 @@ class QueueHandlerTest(BaseTest):
         listener.stop()
         self.assertIsNone(listener._thread)
 
+    def test_queue_listener_multi_start(self):
+        handler = TestHandler(support.Matcher())
+        with logging.handlers.QueueListener(self.queue, handler) as listener:
+            self.assertRaises(RuntimeError, listener.start)
+
+        with listener:
+            self.assertRaises(RuntimeError, listener.start)
+
+        listener.start()
+        listener.stop()
+
     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)
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