https://github.com/python/cpython/commit/5863cd70b8782313b52bb8c71a4127d7ea4c50e9
commit: 5863cd70b8782313b52bb8c71a4127d7ea4c50e9
branch: main
author: Charles Machalow <csm10...@gmail.com>
committer: vsajip <vinay_sa...@yahoo.co.uk>
date: 2025-04-13T08:53:13+01:00
summary:

gh-132106: Ensure that running `logging.handlers.QueueListener` cannot be 
started again (GH-132444)

Prevents a thread leak
Co-authored-by: Bénédikt Tran <10796600+picn...@users.noreply.github.com>

files:
A Misc/NEWS.d/next/Library/2025-04-12-09-30-24.gh-issue-132106.OxUds3.rst
M Doc/library/logging.handlers.rst
M Doc/whatsnew/3.14.rst
M Lib/logging/handlers.py
M Lib/test/test_logging.py

diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst
index b737fe311dfb6e..72312b512a5884 100644
--- a/Doc/library/logging.handlers.rst
+++ b/Doc/library/logging.handlers.rst
@@ -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.
diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index 762d53eeb2df1a..421d12660b7956 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -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
 ---------
diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py
index 0571ed2356345a..2748b5941eade2 100644
--- a/Lib/logging/handlers.py
+++ b/Lib/logging/handlers.py
@@ -1561,6 +1561,9 @@ def start(self):
         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()
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
index 11f6b64abe28fb..9305844829a500 100644
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -4356,6 +4356,17 @@ def test_queue_listener_context_manager(self):
         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
index 00000000000000..b6d58a29f9b42f
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-04-12-09-30-24.gh-issue-132106.OxUds3.rst
@@ -0,0 +1,2 @@
+:meth:`QueueListener.start <logging.handlers.QueueListener.start>` now
+raises a :exc:`RuntimeError` if the listener is already started.

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to