Skip to content

Commit fdcedfd

Browse files
hodamarrvsajip
andauthored
gh-126400: Add TCP socket timeout to SysLogHandler to prevent blocking (GH-126716)
Co-authored-by: Vinay Sajip <[email protected]>
1 parent 002c4e2 commit fdcedfd

File tree

4 files changed

+27
-2
lines changed

4 files changed

+27
-2
lines changed

Doc/library/logging.handlers.rst

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ The :class:`SysLogHandler` class, located in the :mod:`logging.handlers` module,
613613
supports sending logging messages to a remote or local Unix syslog.
614614

615615

616-
.. class:: SysLogHandler(address=('localhost', SYSLOG_UDP_PORT), facility=LOG_USER, socktype=socket.SOCK_DGRAM)
616+
.. class:: SysLogHandler(address=('localhost', SYSLOG_UDP_PORT), facility=LOG_USER, socktype=socket.SOCK_DGRAM, timeout=None)
617617

618618
Returns a new instance of the :class:`SysLogHandler` class intended to
619619
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.
626626
*socktype* argument, which defaults to :const:`socket.SOCK_DGRAM` and thus
627627
opens a UDP socket. To open a TCP socket (for use with the newer syslog
628628
daemons such as rsyslog), specify a value of :const:`socket.SOCK_STREAM`.
629+
If *timeout* is specified, it sets a timeout (in seconds) for the socket operations.
630+
This can help prevent the program from hanging indefinitely if the syslog server is
631+
unreachable. By default, *timeout* is ``None``, meaning no timeout is applied.
632+
633+
629634

630635
Note that if your server is not listening on UDP port 514,
631636
: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.
645650
.. versionchanged:: 3.2
646651
*socktype* was added.
647652

653+
.. versionchanged:: 3.14
654+
*timeout* was added.
648655

649656
.. method:: close()
650657

Lib/logging/handlers.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,7 @@ class SysLogHandler(logging.Handler):
855855
}
856856

857857
def __init__(self, address=('localhost', SYSLOG_UDP_PORT),
858-
facility=LOG_USER, socktype=None):
858+
facility=LOG_USER, socktype=None, timeout=None):
859859
"""
860860
Initialize a handler.
861861
@@ -872,6 +872,7 @@ def __init__(self, address=('localhost', SYSLOG_UDP_PORT),
872872
self.address = address
873873
self.facility = facility
874874
self.socktype = socktype
875+
self.timeout = timeout
875876
self.socket = None
876877
self.createSocket()
877878

@@ -933,6 +934,8 @@ def createSocket(self):
933934
err = sock = None
934935
try:
935936
sock = socket.socket(af, socktype, proto)
937+
if self.timeout:
938+
sock.settimeout(self.timeout)
936939
if socktype == socket.SOCK_STREAM:
937940
sock.connect(sa)
938941
break

Lib/test/test_logging.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import logging.handlers
2323
import logging.config
2424

25+
2526
import codecs
2627
import configparser
2728
import copy
@@ -2095,6 +2096,18 @@ def test_udp_reconnection(self):
20952096
self.handled.wait(support.LONG_TIMEOUT)
20962097
self.assertEqual(self.log_output, b'<11>sp\xc3\xa4m\x00')
20972098

2099+
@patch('socket.socket')
2100+
def test_tcp_timeout(self, mock_socket):
2101+
instance_mock_sock = mock_socket.return_value
2102+
instance_mock_sock.connect.side_effect = socket.timeout
2103+
2104+
with self.assertRaises(socket.timeout):
2105+
logging.handlers.SysLogHandler(address=('localhost', 514),
2106+
socktype=socket.SOCK_STREAM,
2107+
timeout=1)
2108+
2109+
instance_mock_sock.close.assert_called()
2110+
20982111
@unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required")
20992112
class UnixSysLogHandlerTest(SysLogHandlerTest):
21002113

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add a socket *timeout* keyword argument to
2+
:class:`logging.handlers.SysLogHandler`.

0 commit comments

Comments
 (0)