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:
Enzo Candotti 2023-01-20 15:39:25 -03:00
parent 13d3936ed3
commit 2bd6d28ace
5 changed files with 160 additions and 0 deletions

View File

@ -362,6 +362,9 @@ python3-nsenter
python3-pkg-resources
python3-setuptools
#python3.9
python3.9
#openscap
libopenscap25
openscap-common

View File

@ -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

View 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

View File

@ -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

View File

@ -0,0 +1 @@
0001-bpo-44291-Fix-reconnection-in-logging.handlers.SysLo.patch