Fix reconnection in logging.handlers.SysLogHandler
There are lots of exceptions reported in gunicorn.log. That error was due to a bug present on SysLogHandler that was reported on cpython repo but was not fixed for python3.9.2. This change adds python3.9 package to the build system and patches it in order to update SysLogHandler to fix the reconnection bug. Test Plan: PASS: Build python3.9 package. Install libpython3.9-minimal_3.9.2-1.stx.1_amd64.deb and verify that the exceptions are no longer present. Depends-On: https://review.opendev.org/c/starlingx/root/+/873159 Closes-bug: 2006623 Signed-off-by: Enzo Candotti <enzo.candotti@windriver.com> Change-Id: I6eb44544da5c05e712bc89e69193548667c8ab28
This commit is contained in:
parent
13d3936ed3
commit
2bd6d28ace
@ -362,6 +362,9 @@ python3-nsenter
|
||||
python3-pkg-resources
|
||||
python3-setuptools
|
||||
|
||||
#python3.9
|
||||
python3.9
|
||||
|
||||
#openscap
|
||||
libopenscap25
|
||||
openscap-common
|
||||
|
@ -86,6 +86,7 @@ python/dh-python
|
||||
python/python-nss
|
||||
python/python3-nsenter
|
||||
python/python3-setuptools
|
||||
python/python3.9
|
||||
python/zerorpc-python
|
||||
security/efitools
|
||||
security/keyrings.alt
|
||||
|
7
python/python3.9/debian/meta_data.yaml
Normal file
7
python/python3.9/debian/meta_data.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
debname: python3.9
|
||||
debver: 3.9.2-1
|
||||
archive: https://snapshot.debian.org/archive/debian/20210228T205814Z/pool/main/p/python3.9/
|
||||
revision:
|
||||
dist: $STX_DIST
|
||||
PKG_GITREVCOUNT: true
|
@ -0,0 +1,148 @@
|
||||
From a28b8e4a9adeccdd0f68df07b29d5eba8c3d313d Mon Sep 17 00:00:00 2001
|
||||
From: Kirill Pinchuk <192182+cybergrind@users.noreply.github.com>
|
||||
Date: Thu, 5 Aug 2021 16:58:16 +0300
|
||||
Subject: [PATCH] bpo-44291: Fix reconnection in logging.handlers.SysLogHandler
|
||||
(GH-26490)
|
||||
|
||||
Right now SocketHandler and DatagramHandler implement such behavior:
|
||||
|
||||
1 - On close set self.socket = None
|
||||
2 - When trying to send - make socket when it is None
|
||||
|
||||
SysLogHandler doesn't implement this behavior and when you close
|
||||
the socket for some reason (eg. restart of uWSGI server on code change)
|
||||
it leaves it in the closed state, then raises an error when you try to
|
||||
send any message because it is closed.
|
||||
|
||||
--- Logging error ---
|
||||
Traceback (most recent call last):
|
||||
File "/usr/lib/python3.9/logging/handlers.py", line 959, in emit
|
||||
self.socket.sendto(msg, self.address)
|
||||
OSError: [Errno 9] Bad file descriptor
|
||||
|
||||
This patch adds reconnection logic for UDP/TCP sockets as well as UNIX
|
||||
sockets.
|
||||
|
||||
Signed-off-by: Enzo Candotti <enzo.candotti@windriver.com>
|
||||
---
|
||||
Lib/logging/handlers.py | 63 ++++++++++++++++++++++++----------------
|
||||
Lib/test/test_logging.py | 8 +++++
|
||||
2 files changed, 46 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py
|
||||
index 867ef4ebc7..ff8f9e534f 100644
|
||||
--- a/Lib/logging/handlers.py
|
||||
+++ b/Lib/logging/handlers.py
|
||||
@@ -829,6 +829,36 @@ class SysLogHandler(logging.Handler):
|
||||
self.address = address
|
||||
self.facility = facility
|
||||
self.socktype = socktype
|
||||
+ self.socket = None
|
||||
+ self.createSocket()
|
||||
+
|
||||
+ def _connect_unixsocket(self, address):
|
||||
+ use_socktype = self.socktype
|
||||
+ if use_socktype is None:
|
||||
+ use_socktype = socket.SOCK_DGRAM
|
||||
+ self.socket = socket.socket(socket.AF_UNIX, use_socktype)
|
||||
+ try:
|
||||
+ self.socket.connect(address)
|
||||
+ # it worked, so set self.socktype to the used type
|
||||
+ self.socktype = use_socktype
|
||||
+ except OSError:
|
||||
+ self.socket.close()
|
||||
+ if self.socktype is not None:
|
||||
+ # user didn't specify falling back, so fail
|
||||
+ raise
|
||||
+ use_socktype = socket.SOCK_STREAM
|
||||
+ self.socket = socket.socket(socket.AF_UNIX, use_socktype)
|
||||
+ try:
|
||||
+ self.socket.connect(address)
|
||||
+ # it worked, so set self.socktype to the used type
|
||||
+ self.socktype = use_socktype
|
||||
+ except OSError:
|
||||
+ self.socket.close()
|
||||
+ raise
|
||||
+
|
||||
+ def createSocket(self):
|
||||
+ address = self.address
|
||||
+ socktype = self.socktype
|
||||
|
||||
if isinstance(address, str):
|
||||
self.unixsocket = True
|
||||
@@ -865,30 +895,6 @@ class SysLogHandler(logging.Handler):
|
||||
self.socket = sock
|
||||
self.socktype = socktype
|
||||
|
||||
- def _connect_unixsocket(self, address):
|
||||
- use_socktype = self.socktype
|
||||
- if use_socktype is None:
|
||||
- use_socktype = socket.SOCK_DGRAM
|
||||
- self.socket = socket.socket(socket.AF_UNIX, use_socktype)
|
||||
- try:
|
||||
- self.socket.connect(address)
|
||||
- # it worked, so set self.socktype to the used type
|
||||
- self.socktype = use_socktype
|
||||
- except OSError:
|
||||
- self.socket.close()
|
||||
- if self.socktype is not None:
|
||||
- # user didn't specify falling back, so fail
|
||||
- raise
|
||||
- use_socktype = socket.SOCK_STREAM
|
||||
- self.socket = socket.socket(socket.AF_UNIX, use_socktype)
|
||||
- try:
|
||||
- self.socket.connect(address)
|
||||
- # it worked, so set self.socktype to the used type
|
||||
- self.socktype = use_socktype
|
||||
- except OSError:
|
||||
- self.socket.close()
|
||||
- raise
|
||||
-
|
||||
def encodePriority(self, facility, priority):
|
||||
"""
|
||||
Encode the facility and priority. You can pass in strings or
|
||||
@@ -908,7 +914,10 @@ class SysLogHandler(logging.Handler):
|
||||
"""
|
||||
self.acquire()
|
||||
try:
|
||||
- self.socket.close()
|
||||
+ sock = self.socket
|
||||
+ if sock:
|
||||
+ self.socket = None
|
||||
+ sock.close()
|
||||
logging.Handler.close(self)
|
||||
finally:
|
||||
self.release()
|
||||
@@ -948,6 +957,10 @@ class SysLogHandler(logging.Handler):
|
||||
# Message is a string. Convert to bytes as required by RFC 5424
|
||||
msg = msg.encode('utf-8')
|
||||
msg = prio + msg
|
||||
+
|
||||
+ if not self.socket:
|
||||
+ self.createSocket()
|
||||
+
|
||||
if self.unixsocket:
|
||||
try:
|
||||
self.socket.send(msg)
|
||||
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
|
||||
index a6cd291c9a..e795533775 100644
|
||||
--- a/Lib/test/test_logging.py
|
||||
+++ b/Lib/test/test_logging.py
|
||||
@@ -1931,6 +1931,14 @@ class SysLogHandlerTest(BaseTest):
|
||||
self.handled.wait()
|
||||
self.assertEqual(self.log_output, b'<11>h\xc3\xa4m-sp\xc3\xa4m')
|
||||
|
||||
+ def test_udp_reconnection(self):
|
||||
+ logger = logging.getLogger("slh")
|
||||
+ self.sl_hdlr.close()
|
||||
+ self.handled.clear()
|
||||
+ logger.error("sp\xe4m")
|
||||
+ self.handled.wait(0.1)
|
||||
+ self.assertEqual(self.log_output, b'<11>sp\xc3\xa4m\x00')
|
||||
+
|
||||
@unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required")
|
||||
class UnixSysLogHandlerTest(SysLogHandlerTest):
|
||||
|
||||
--
|
||||
2.25.1
|
||||
|
1
python/python3.9/debian/patches/series
Normal file
1
python/python3.9/debian/patches/series
Normal file
@ -0,0 +1 @@
|
||||
0001-bpo-44291-Fix-reconnection-in-logging.handlers.SysLo.patch
|
Loading…
Reference in New Issue
Block a user