diff --git a/swift/common/utils.py b/swift/common/utils.py index c750678736..9155a415ce 100644 --- a/swift/common/utils.py +++ b/swift/common/utils.py @@ -2015,9 +2015,18 @@ def get_hub(): In contrast, both poll() and select() specify the set of interesting file descriptors with each call, so there's no problem with forking. + + As eventlet monkey patching is now done before call get_hub() in wsgi.py + if we use 'import select' we get the eventlet version, but since version + 0.20.0 eventlet removed select.poll() function in patched select (see: + http://eventlet.net/doc/changelog.html and + https://github.com/eventlet/eventlet/commit/614a20462). + + We use eventlet.patcher.original function to get python select module + to test if poll() is available on platform. """ try: - import select + select = eventlet.patcher.original('select') if hasattr(select, "poll"): return "poll" return "selects" diff --git a/test/unit/common/test_utils.py b/test/unit/common/test_utils.py index 3d4bd9f7d9..fde083a335 100644 --- a/test/unit/common/test_utils.py +++ b/test/unit/common/test_utils.py @@ -4542,6 +4542,38 @@ class TestFileLikeIter(unittest.TestCase): iter_file.close() self.assertTrue(iter_file.closed) + def test_get_hub(self): + # This test mock the eventlet.green.select module without poll + # as in eventlet > 0.20 + # https://github.com/eventlet/eventlet/commit/614a20462 + # We add __original_module_select to sys.modules to mock usage + # of eventlet.patcher.original + + class SelectWithPoll(object): + def poll(): + pass + + class SelectWithoutPoll(object): + pass + + # Platform with poll() that call get_hub before eventlet patching + with mock.patch.dict('sys.modules', + {'select': SelectWithPoll, + '__original_module_select': SelectWithPoll}): + self.assertEqual(utils.get_hub(), 'poll') + + # Platform with poll() that call get_hub after eventlet patching + with mock.patch.dict('sys.modules', + {'select': SelectWithoutPoll, + '__original_module_select': SelectWithPoll}): + self.assertEqual(utils.get_hub(), 'poll') + + # Platform without poll() -- before or after patching doesn't matter + with mock.patch.dict('sys.modules', + {'select': SelectWithoutPoll, + '__original_module_select': SelectWithoutPoll}): + self.assertEqual(utils.get_hub(), 'selects') + class TestStatsdLogging(unittest.TestCase): def setUp(self):