summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHod <104125115+hodamarr@users.noreply.github.com>2025-01-29 19:37:43 (GMT)
committerGitHub <noreply@github.com>2025-01-29 19:37:43 (GMT)
commitfdcedfd3cf1a645634dee354ee349d966c56348f (patch)
treee1461e8306a174a43187433a1d8ad5b9b9c65e61
parent002c4e2982910937f35a4b80ab94b07c3c16067f (diff)
downloadcpython-fdcedfd3cf1a645634dee354ee349d966c56348f.zip
cpython-fdcedfd3cf1a645634dee354ee349d966c56348f.tar.gz
cpython-fdcedfd3cf1a645634dee354ee349d966c56348f.tar.bz2
gh-126400: Add TCP socket timeout to SysLogHandler to prevent blocking (GH-126716)
Co-authored-by: Vinay Sajip <vinay_sajip@yahoo.co.uk>
-rw-r--r--Doc/library/logging.handlers.rst9
-rw-r--r--Lib/logging/handlers.py5
-rw-r--r--Lib/test/test_logging.py13
-rw-r--r--Misc/NEWS.d/next/Library/2025-01-29-13-37-18.gh-issue-126400.DaBaR3.rst2
4 files changed, 27 insertions, 2 deletions
diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst
index 5a081f9..ffb5459 100644
--- a/Doc/library/logging.handlers.rst
+++ b/Doc/library/logging.handlers.rst
@@ -613,7 +613,7 @@ The :class:`SysLogHandler` class, located in the :mod:`logging.handlers` module,
supports sending logging messages to a remote or local Unix syslog.
-.. class:: SysLogHandler(address=('localhost', SYSLOG_UDP_PORT), facility=LOG_USER, socktype=socket.SOCK_DGRAM)
+.. class:: SysLogHandler(address=('localhost', SYSLOG_UDP_PORT), facility=LOG_USER, socktype=socket.SOCK_DGRAM, timeout=None)
Returns a new instance of the :class:`SysLogHandler` class intended to
communicate with a remote Unix machine whose address is given by *address* in
@@ -626,6 +626,11 @@ supports sending logging messages to a remote or local Unix syslog.
*socktype* argument, which defaults to :const:`socket.SOCK_DGRAM` and thus
opens a UDP socket. To open a TCP socket (for use with the newer syslog
daemons such as rsyslog), specify a value of :const:`socket.SOCK_STREAM`.
+ If *timeout* is specified, it sets a timeout (in seconds) for the socket operations.
+ This can help prevent the program from hanging indefinitely if the syslog server is
+ unreachable. By default, *timeout* is ``None``, meaning no timeout is applied.
+
+
Note that if your server is not listening on UDP port 514,
:class:`SysLogHandler` may appear not to work. In that case, check what
@@ -645,6 +650,8 @@ supports sending logging messages to a remote or local Unix syslog.
.. versionchanged:: 3.2
*socktype* was added.
+ .. versionchanged:: 3.14
+ *timeout* was added.
.. method:: close()
diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py
index 1cba64f..017c9ab 100644
--- a/Lib/logging/handlers.py
+++ b/Lib/logging/handlers.py
@@ -855,7 +855,7 @@ class SysLogHandler(logging.Handler):
}
def __init__(self, address=('localhost', SYSLOG_UDP_PORT),
- facility=LOG_USER, socktype=None):
+ facility=LOG_USER, socktype=None, timeout=None):
"""
Initialize a handler.
@@ -872,6 +872,7 @@ class SysLogHandler(logging.Handler):
self.address = address
self.facility = facility
self.socktype = socktype
+ self.timeout = timeout
self.socket = None
self.createSocket()
@@ -933,6 +934,8 @@ class SysLogHandler(logging.Handler):
err = sock = None
try:
sock = socket.socket(af, socktype, proto)
+ if self.timeout:
+ sock.settimeout(self.timeout)
if socktype == socket.SOCK_STREAM:
sock.connect(sa)
break
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
index 2e5f647..e34fe45 100644
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -22,6 +22,7 @@ import logging
import logging.handlers
import logging.config
+
import codecs
import configparser
import copy
@@ -2095,6 +2096,18 @@ class SysLogHandlerTest(BaseTest):
self.handled.wait(support.LONG_TIMEOUT)
self.assertEqual(self.log_output, b'<11>sp\xc3\xa4m\x00')
+ @patch('socket.socket')
+ def test_tcp_timeout(self, mock_socket):
+ instance_mock_sock = mock_socket.return_value
+ instance_mock_sock.connect.side_effect = socket.timeout
+
+ with self.assertRaises(socket.timeout):
+ logging.handlers.SysLogHandler(address=('localhost', 514),
+ socktype=socket.SOCK_STREAM,
+ timeout=1)
+
+ instance_mock_sock.close.assert_called()
+
@unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required")
class UnixSysLogHandlerTest(SysLogHandlerTest):
diff --git a/Misc/NEWS.d/next/Library/2025-01-29-13-37-18.gh-issue-126400.DaBaR3.rst b/Misc/NEWS.d/next/Library/2025-01-29-13-37-18.gh-issue-126400.DaBaR3.rst
new file mode 100644
index 0000000..1532faf
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-01-29-13-37-18.gh-issue-126400.DaBaR3.rst
@@ -0,0 +1,2 @@
+Add a socket *timeout* keyword argument to
+:class:`logging.handlers.SysLogHandler`.