From 207dd9b49d7d53a9faa4849af2c40bb875416fce Mon Sep 17 00:00:00 2001 From: Darrell Bishop Date: Thu, 30 Jul 2015 14:32:08 -0700 Subject: [PATCH] Fix regression in WSGI server SIGHUP behavior The SIGHUP receipt used to pop us out of an os.wait() where now, it's in a "green" wait() and Timeout() combo, some part of which eats the signal receipt. This causes the while loop condition to never get checked and SIGHUP no longer works as a server reload command. The fix is to loop at least every 0.5 seconds, as a trade-off between not busy-waiting and checking the "keep running" condition often enough to feel responsive. Change-Id: I95283b8b7cfc2998ab5813e0ad3ca1fa231696c8 Closes-Bug: #1479972 --- swift/common/wsgi.py | 8 ++++++-- test/unit/common/test_wsgi.py | 7 ++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/swift/common/wsgi.py b/swift/common/wsgi.py index 28810f6f8d..fbb3d5d009 100644 --- a/swift/common/wsgi.py +++ b/swift/common/wsgi.py @@ -461,10 +461,14 @@ class WorkersStrategy(object): def loop_timeout(self): """ - :returns: None; to block in :py:func:`green.os.wait` + We want to keep from busy-waiting, but we also need a non-None value so + the main loop gets a chance to tell whether it should keep running or + not (e.g. SIGHUP received). + + So we return 0.5. """ - return None + return 0.5 def bind_ports(self): """ diff --git a/test/unit/common/test_wsgi.py b/test/unit/common/test_wsgi.py index ee83ebfc4a..cf92edeb76 100644 --- a/test/unit/common/test_wsgi.py +++ b/test/unit/common/test_wsgi.py @@ -1090,9 +1090,10 @@ class TestWorkersStrategy(unittest.TestCase): self.addCleanup(patcher.stop) def test_loop_timeout(self): - # This strategy should block in the green.os.wait() until a worker - # process exits. - self.assertEqual(None, self.strategy.loop_timeout()) + # This strategy should sit in the green.os.wait() for a bit (to avoid + # busy-waiting) but not forever (so the keep-running flag actually + # gets checked). + self.assertEqual(0.5, self.strategy.loop_timeout()) def test_binding(self): self.assertEqual(None, self.strategy.bind_ports())