From 0d292febb8f7c1f56b2081be96ca836253b4808c Mon Sep 17 00:00:00 2001 From: Xiang Zhang Date: Sat, 20 May 2017 15:04:48 +0800 Subject: [PATCH 1/6] bpo-30378: Fix the problem that SysLogHandler can't handle IPv6 addresses --- Lib/logging/handlers.py | 26 +++++++++++++++++++++----- Lib/test/test_logging.py | 22 ++++++++++++++++++++-- Misc/NEWS | 3 +++ 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py index 2356f8d3d2d8ce..bdb04a06429ac1 100644 --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -812,6 +812,7 @@ def __init__(self, address=('localhost', SYSLOG_UDP_PORT), self.address = address self.facility = facility self.socktype = socktype + self.formatter = None if isinstance(address, str): self.unixsocket = True @@ -827,11 +828,26 @@ def __init__(self, address=('localhost', SYSLOG_UDP_PORT), self.unixsocket = False if socktype is None: socktype = socket.SOCK_DGRAM - self.socket = socket.socket(socket.AF_INET, socktype) - if socktype == socket.SOCK_STREAM: - self.socket.connect(address) - self.socktype = socktype - self.formatter = None + host, port = address + err = None + for res in socket.getaddrinfo(host, port, 0, socktype): + af, socktype, proto, cannonname, sa = res + sock = None + try: + sock = socket.socket(af, socktype, proto) + if socktype == socket.SOCK_STREAM: + sock.connect(sa) + self.socket = sock + self.socktype = socktype + return + except OSError as _: + err = _ + if sock is not None: + sock.close() + if err is not None: + raise err + else: + raise socket.error("getaddrinfo returns an empty list") def _connect_unixsocket(self, address): use_socktype = self.socktype diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 85c82251e95abb..cef3eccf6c733d 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -1678,7 +1678,7 @@ def setUp(self): server.ready.wait() hcls = logging.handlers.SysLogHandler if isinstance(server.server_address, tuple): - self.sl_hdlr = hcls(('localhost', server.port)) + self.sl_hdlr = hcls((server.server_address[0], server.port)) else: self.sl_hdlr = hcls(server.server_address) self.log_output = '' @@ -1738,6 +1738,24 @@ def tearDown(self): SysLogHandlerTest.tearDown(self) support.unlink(self.address) +@unittest.skipUnless(support.IPV6_ENABLED, + 'IPv6 support required for this test.') +@unittest.skipUnless(threading, 'Threading required for this test.') +class IPv6SyslogHandlerTest(SysLogHandlerTest): + + """Test for SysLogHandler with IPv6 host.""" + + server_class = TestUDPServer + address = ('::1', 0) + + def setUp(self): + self.server_class.address_family = socket.AF_INET6 + super(IPv6SyslogHandlerTest, self).setUp() + + def tearDown(self): + self.server_class.address_family = socket.AF_INET + super(IPv6SyslogHandlerTest, self).tearDown() + @unittest.skipUnless(threading, 'Threading required for this test.') class HTTPHandlerTest(BaseTest): """Test for HTTPHandler.""" @@ -4404,7 +4422,7 @@ def test_main(): QueueHandlerTest, ShutdownTest, ModuleLevelMiscTest, BasicConfigTest, LoggerAdapterTest, LoggerTest, SMTPHandlerTest, FileHandlerTest, RotatingFileHandlerTest, LastResortTest, LogRecordTest, - ExceptionTest, SysLogHandlerTest, HTTPHandlerTest, + ExceptionTest, SysLogHandlerTest, IPv6SyslogHandlerTest, HTTPHandlerTest, NTEventLogHandlerTest, TimedRotatingFileHandlerTest, UnixSocketHandlerTest, UnixDatagramHandlerTest, UnixSysLogHandlerTest, MiscTestCase diff --git a/Misc/NEWS b/Misc/NEWS index c6aed7f48c8dcb..777bf192cdfec3 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -327,6 +327,9 @@ Extension Modules Library ------- +- bpo-30378: Fix the problem that logging.handlers.SysLogHandler cannot + handle IPv6 addresses. + - bpo-30149: inspect.signature() now supports callables with variable-argument parameters wrapped with partialmethod. Patch by Dong-hee Na. From 9ae2e025b187b9a1b8df729fd4fbafa9466df21b Mon Sep 17 00:00:00 2001 From: Xiang Zhang Date: Sat, 20 May 2017 15:52:57 +0800 Subject: [PATCH 2/6] use OSError instead of socket.error --- Lib/logging/handlers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py index bdb04a06429ac1..785113785390f8 100644 --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -847,7 +847,7 @@ def __init__(self, address=('localhost', SYSLOG_UDP_PORT), if err is not None: raise err else: - raise socket.error("getaddrinfo returns an empty list") + raise OSError("getaddrinfo returns an empty list") def _connect_unixsocket(self, address): use_socktype = self.socktype From f7ec0562151a8f68bd6d45ffaa057ea09ae38b24 Mon Sep 17 00:00:00 2001 From: Xiang Zhang Date: Sat, 20 May 2017 16:09:14 +0800 Subject: [PATCH 3/6] fix typo --- Lib/test/test_logging.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index cef3eccf6c733d..1ca7c74d22e343 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -1741,7 +1741,7 @@ def tearDown(self): @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 support required for this test.') @unittest.skipUnless(threading, 'Threading required for this test.') -class IPv6SyslogHandlerTest(SysLogHandlerTest): +class IPv6SysLogHandlerTest(SysLogHandlerTest): """Test for SysLogHandler with IPv6 host.""" @@ -4422,7 +4422,7 @@ def test_main(): QueueHandlerTest, ShutdownTest, ModuleLevelMiscTest, BasicConfigTest, LoggerAdapterTest, LoggerTest, SMTPHandlerTest, FileHandlerTest, RotatingFileHandlerTest, LastResortTest, LogRecordTest, - ExceptionTest, SysLogHandlerTest, IPv6SyslogHandlerTest, HTTPHandlerTest, + ExceptionTest, SysLogHandlerTest, IPv6SysLogHandlerTest, HTTPHandlerTest, NTEventLogHandlerTest, TimedRotatingFileHandlerTest, UnixSocketHandlerTest, UnixDatagramHandlerTest, UnixSysLogHandlerTest, MiscTestCase From 3546876cb843a1fbe2b692b4a25a7ec84c4f7b3b Mon Sep 17 00:00:00 2001 From: Xiang Zhang Date: Sat, 20 May 2017 17:07:22 +0800 Subject: [PATCH 4/6] fix forgottened class name change --- Lib/test/test_logging.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 1ca7c74d22e343..ed25d3e9207373 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -1750,11 +1750,11 @@ class IPv6SysLogHandlerTest(SysLogHandlerTest): def setUp(self): self.server_class.address_family = socket.AF_INET6 - super(IPv6SyslogHandlerTest, self).setUp() + super(IPv6SysLogHandlerTest, self).setUp() def tearDown(self): self.server_class.address_family = socket.AF_INET - super(IPv6SyslogHandlerTest, self).tearDown() + super(IPv6SysLogHandlerTest, self).tearDown() @unittest.skipUnless(threading, 'Threading required for this test.') class HTTPHandlerTest(BaseTest): From b50986b85ee53feac536a1d3e26c2db5458633ab Mon Sep 17 00:00:00 2001 From: Xiang Zhang Date: Sat, 20 May 2017 20:32:45 +0800 Subject: [PATCH 5/6] address part of Vinay's first --- Lib/logging/handlers.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py index 785113785390f8..065b5d60c71396 100644 --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -812,7 +812,6 @@ def __init__(self, address=('localhost', SYSLOG_UDP_PORT), self.address = address self.facility = facility self.socktype = socktype - self.formatter = None if isinstance(address, str): self.unixsocket = True @@ -831,7 +830,7 @@ def __init__(self, address=('localhost', SYSLOG_UDP_PORT), host, port = address err = None for res in socket.getaddrinfo(host, port, 0, socktype): - af, socktype, proto, cannonname, sa = res + af, socktype, proto, _, sa = res sock = None try: sock = socket.socket(af, socktype, proto) @@ -886,7 +885,7 @@ def encodePriority(self, facility, priority): priority = self.priority_names[priority] return (facility << 3) | priority - def close (self): + def close(self): """ Closes the socket. """ From 07e0691189e2234744fcd766d3ed1392de5bb0f2 Mon Sep 17 00:00:00 2001 From: Xiang Zhang Date: Sun, 21 May 2017 21:29:50 +0800 Subject: [PATCH 6/6] address more Vinay's comments --- Lib/logging/handlers.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py index 065b5d60c71396..2f934b33071563 100644 --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -828,25 +828,25 @@ def __init__(self, address=('localhost', SYSLOG_UDP_PORT), if socktype is None: socktype = socket.SOCK_DGRAM host, port = address - err = None - for res in socket.getaddrinfo(host, port, 0, socktype): + ress = socket.getaddrinfo(host, port, 0, socktype) + if not ress: + raise OSError("getaddrinfo returns an empty list") + for res in ress: af, socktype, proto, _, sa = res - sock = None + err = sock = None try: sock = socket.socket(af, socktype, proto) if socktype == socket.SOCK_STREAM: sock.connect(sa) - self.socket = sock - self.socktype = socktype - return - except OSError as _: - err = _ + break + except OSError as exc: + err = exc if sock is not None: sock.close() if err is not None: raise err - else: - raise OSError("getaddrinfo returns an empty list") + self.socket = sock + self.socktype = socktype def _connect_unixsocket(self, address): use_socktype = self.socktype