diff -Nru swift-2.7.1/debian/changelog swift-2.7.1/debian/changelog --- swift-2.7.1/debian/changelog 2017-02-27 10:59:47.000000000 -0700 +++ swift-2.7.1/debian/changelog 2017-05-22 12:58:01.000000000 -0700 @@ -1,3 +1,13 @@ +swift (2.7.1-0ubuntu2) xenial; urgency=medium + + * Fix issue where swift daemons crash while writing logs to a stopped + rsyslogd /dev/log socket. (LP: #1683076) + - d/patches/fix-infinite-recursion-logging.patch: Cherry-picked from + upstream stable/newton branch to avoid infinite loops when logging + while rsyslogd is stopped. + + -- Billy Olsen Mon, 22 May 2017 12:58:01 -0700 + swift (2.7.1-0ubuntu1) xenial; urgency=medium * New upstream point release for Openstack Mitaka. (LP: #1668313) diff -Nru swift-2.7.1/debian/patches/fix-infinite-recursion-logging.patch swift-2.7.1/debian/patches/fix-infinite-recursion-logging.patch --- swift-2.7.1/debian/patches/fix-infinite-recursion-logging.patch 1969-12-31 17:00:00.000000000 -0700 +++ swift-2.7.1/debian/patches/fix-infinite-recursion-logging.patch 2017-05-22 12:58:01.000000000 -0700 @@ -0,0 +1,144 @@ +From 83508b97b352ef903878510f85794cd54da53155 Mon Sep 17 00:00:00 2001 +From: Samuel Merritt +Date: Wed, 23 Mar 2016 13:51:47 -0700 +Subject: [PATCH 1/1] Fix infinite recursion during logging when syslog is down + +Change-Id: Ia9ecffc88ce43616977e141498e5ee404f2c29c4 +(cherry picked from commit 95efd3f9035ec4141e1b182516f040a59a3e5aa6) +--- + swift/common/utils.py | 54 +++++++++++++++++++++++++++++++++++------- + test/unit/common/test_utils.py | 42 ++++++++++++++++++++++++++++++++ + 2 files changed, 88 insertions(+), 8 deletions(-) + +Forwarded: Not-Needed +Bug: https://launchpad.net/bugs/1683076 +Origin: upstream, https://github.com/openstack/swift/commit/95efd3f9035ec4141e1b182516f040a59a3e5aa6 + +diff --git a/swift/common/utils.py b/swift/common/utils.py +index 210dd9f4..61c09697 100644 +--- a/swift/common/utils.py ++++ b/swift/common/utils.py +@@ -1232,21 +1232,59 @@ class NullLogger(object): + + class LoggerFileObject(object): + ++ # Note: this is greenthread-local storage ++ _cls_thread_local = threading.local() ++ + def __init__(self, logger, log_type='STDOUT'): + self.logger = logger + self.log_type = log_type + + def write(self, value): +- value = value.strip() +- if value: +- if 'Connection reset by peer' in value: +- self.logger.error( +- _('%s: Connection reset by peer'), self.log_type) +- else: +- self.logger.error(_('%s: %s'), self.log_type, value) ++ # We can get into a nasty situation when logs are going to syslog ++ # and syslog dies. ++ # ++ # It's something like this: ++ # ++ # (A) someone logs something ++ # ++ # (B) there's an exception in sending to /dev/log since syslog is ++ # not working ++ # ++ # (C) logging takes that exception and writes it to stderr (see ++ # logging.Handler.handleError) ++ # ++ # (D) stderr was replaced with a LoggerFileObject at process start, ++ # so the LoggerFileObject takes the provided string and tells ++ # its logger to log it (to syslog, naturally). ++ # ++ # Then, steps B through D repeat until we run out of stack. ++ if getattr(self._cls_thread_local, 'already_called_write', False): ++ return ++ ++ self._cls_thread_local.already_called_write = True ++ try: ++ value = value.strip() ++ if value: ++ if 'Connection reset by peer' in value: ++ self.logger.error( ++ _('%s: Connection reset by peer'), self.log_type) ++ else: ++ self.logger.error(_('%(type)s: %(value)s'), ++ {'type': self.log_type, 'value': value}) ++ finally: ++ self._cls_thread_local.already_called_write = False + + def writelines(self, values): +- self.logger.error(_('%s: %s'), self.log_type, '#012'.join(values)) ++ if getattr(self._cls_thread_local, 'already_called_writelines', False): ++ return ++ ++ self._cls_thread_local.already_called_writelines = True ++ try: ++ self.logger.error(_('%(type)s: %(value)s'), ++ {'type': self.log_type, ++ 'value': '#012'.join(values)}) ++ finally: ++ self._cls_thread_local.already_called_writelines = False + + def close(self): + pass +diff --git a/test/unit/common/test_utils.py b/test/unit/common/test_utils.py +index 409990ad..c2a9e93c 100644 +--- a/test/unit/common/test_utils.py ++++ b/test/unit/common/test_utils.py +@@ -1264,6 +1264,48 @@ class TestUtils(unittest.TestCase): + self.assertRaises(IOError, lfo.readline, 1024) + lfo.tell() + ++ def test_LoggerFileObject_recursion(self): ++ crashy_calls = [0] ++ ++ class CrashyLogger(logging.Handler): ++ def emit(self, record): ++ crashy_calls[0] += 1 ++ try: ++ # Pretend to be trying to send to syslog, but syslogd is ++ # dead. We need the raise here to set sys.exc_info. ++ raise socket.error(errno.ENOTCONN, "This is an ex-syslog") ++ except socket.error: ++ self.handleError(record) ++ ++ logger = logging.getLogger() ++ logger.addHandler(CrashyLogger()) ++ ++ # Set up some real file descriptors for stdio. If you run ++ # nosetests with "-s", you already have real files there, but ++ # otherwise they're StringIO objects. ++ # ++ # In any case, since capture_stdio() closes sys.stdin and friends, ++ # we'd want to set up some sacrificial files so as to not goof up ++ # the testrunner. ++ new_stdin = open(os.devnull, 'r+b') ++ new_stdout = open(os.devnull, 'w+b') ++ new_stderr = open(os.devnull, 'w+b') ++ ++ with contextlib.closing(new_stdin), contextlib.closing(new_stdout), \ ++ contextlib.closing(new_stderr): ++ # logging.raiseExceptions is set to False in test/__init__.py, but ++ # is True in Swift daemons, and the error doesn't manifest without ++ # it. ++ with mock.patch('sys.stdin', new_stdin), \ ++ mock.patch('sys.stdout', new_stdout), \ ++ mock.patch('sys.stderr', new_stderr), \ ++ mock.patch.object(logging, 'raiseExceptions', True): ++ # Note: since stdio is hooked up to /dev/null in here, using ++ # pdb is basically impossible. Sorry about that. ++ utils.capture_stdio(logger) ++ logger.info("I like ham") ++ self.assertTrue(crashy_calls[0], 1) ++ + def test_parse_options(self): + # Get a file that is definitely on disk + with NamedTemporaryFile() as f: +-- +2.11.0 + diff -Nru swift-2.7.1/debian/patches/series swift-2.7.1/debian/patches/series --- swift-2.7.1/debian/patches/series 2017-02-27 10:59:47.000000000 -0700 +++ swift-2.7.1/debian/patches/series 2017-05-22 12:57:45.000000000 -0700 @@ -1,2 +1,3 @@ drop-sphinx-git.patch fix-doc-no-network.patch +fix-infinite-recursion-logging.patch