Skip to content

Commit 4cbac84

Browse files
committed
bpo-44291: Fix reconnection in logging.handlers.SysLogHandler (GH-26490)
1 parent 8916633 commit 4cbac84

File tree

2 files changed

+46
-25
lines changed

2 files changed

+46
-25
lines changed

Lib/logging/handlers.py

+38-25
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,36 @@ def __init__(self, address=('localhost', SYSLOG_UDP_PORT),
834834
self.address = address
835835
self.facility = facility
836836
self.socktype = socktype
837+
self.socket = None
838+
self.createSocket()
839+
840+
def _connect_unixsocket(self, address):
841+
use_socktype = self.socktype
842+
if use_socktype is None:
843+
use_socktype = socket.SOCK_DGRAM
844+
self.socket = socket.socket(socket.AF_UNIX, use_socktype)
845+
try:
846+
self.socket.connect(address)
847+
# it worked, so set self.socktype to the used type
848+
self.socktype = use_socktype
849+
except OSError:
850+
self.socket.close()
851+
if self.socktype is not None:
852+
# user didn't specify falling back, so fail
853+
raise
854+
use_socktype = socket.SOCK_STREAM
855+
self.socket = socket.socket(socket.AF_UNIX, use_socktype)
856+
try:
857+
self.socket.connect(address)
858+
# it worked, so set self.socktype to the used type
859+
self.socktype = use_socktype
860+
except OSError:
861+
self.socket.close()
862+
raise
863+
864+
def createSocket(self):
865+
address = self.address
866+
socktype = self.socktype
837867

838868
if isinstance(address, str):
839869
self.unixsocket = True
@@ -870,30 +900,6 @@ def __init__(self, address=('localhost', SYSLOG_UDP_PORT),
870900
self.socket = sock
871901
self.socktype = socktype
872902

873-
def _connect_unixsocket(self, address):
874-
use_socktype = self.socktype
875-
if use_socktype is None:
876-
use_socktype = socket.SOCK_DGRAM
877-
self.socket = socket.socket(socket.AF_UNIX, use_socktype)
878-
try:
879-
self.socket.connect(address)
880-
# it worked, so set self.socktype to the used type
881-
self.socktype = use_socktype
882-
except OSError:
883-
self.socket.close()
884-
if self.socktype is not None:
885-
# user didn't specify falling back, so fail
886-
raise
887-
use_socktype = socket.SOCK_STREAM
888-
self.socket = socket.socket(socket.AF_UNIX, use_socktype)
889-
try:
890-
self.socket.connect(address)
891-
# it worked, so set self.socktype to the used type
892-
self.socktype = use_socktype
893-
except OSError:
894-
self.socket.close()
895-
raise
896-
897903
def encodePriority(self, facility, priority):
898904
"""
899905
Encode the facility and priority. You can pass in strings or
@@ -913,7 +919,10 @@ def close(self):
913919
"""
914920
self.acquire()
915921
try:
916-
self.socket.close()
922+
sock = self.socket
923+
if sock:
924+
self.socket = None
925+
sock.close()
917926
logging.Handler.close(self)
918927
finally:
919928
self.release()
@@ -953,6 +962,10 @@ def emit(self, record):
953962
# Message is a string. Convert to bytes as required by RFC 5424
954963
msg = msg.encode('utf-8')
955964
msg = prio + msg
965+
966+
if not self.socket:
967+
self.createSocket()
968+
956969
if self.unixsocket:
957970
try:
958971
self.socket.send(msg)

Lib/test/test_logging.py

+8
Original file line numberDiff line numberDiff line change
@@ -1939,6 +1939,14 @@ def test_output(self):
19391939
self.handled.wait()
19401940
self.assertEqual(self.log_output, b'<11>h\xc3\xa4m-sp\xc3\xa4m')
19411941

1942+
def test_udp_reconnection(self):
1943+
logger = logging.getLogger("slh")
1944+
self.sl_hdlr.close()
1945+
self.handled.clear()
1946+
logger.error("sp\xe4m")
1947+
self.handled.wait(0.1)
1948+
self.assertEqual(self.log_output, b'<11>sp\xc3\xa4m\x00')
1949+
19421950
@unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required")
19431951
class UnixSysLogHandlerTest(SysLogHandlerTest):
19441952

0 commit comments

Comments
 (0)