Restore correct signal handling in Python3

The patch c8c8946d32 broke the original
fix cad75e4e13 that ensured eventlet could
be interrupted while sleeping after PEP475 was implemented in Python
3.5. Eventlet monkey-patches the signal module with its own version, so
we have to look up the original module to determine whether the
underlying OS actually supports the poll() function.

Change-Id: Ia712c9a83d8081bf0b5e6fe36f169f9028aae3dc
Closes-Bug: #1803731
Related-Bug: #1788022
Related-Bug: #1705047
(cherry picked from commit 159ef2e1d2)
This commit is contained in:
Zane Bitter 2018-12-10 19:42:30 +13:00
parent d555763f8f
commit d1295d45ee
2 changed files with 18 additions and 5 deletions

View File

@ -28,7 +28,6 @@ import io
import logging
import os
import random
import select
import signal
import six
import sys
@ -204,8 +203,9 @@ class SignalHandler(object):
For Python 3.5 and later, deal with the changes in PEP 475 that prevent
a signal from interrupting eventlet's call to poll() or sleep().
"""
select_module = eventlet.patcher.original('select')
self.__force_interrupt_on_signal = (sys.version_info >= (3, 5) and
hasattr(select, 'poll'))
hasattr(select_module, 'poll'))
if self.__force_interrupt_on_signal:
try:

View File

@ -478,15 +478,28 @@ class ProcessLauncherTest(base.ServiceBaseTestCase):
signal_handler.clear()
@mock.patch('sys.version_info', (3, 5))
@mock.patch.object(service, 'select', spec=[])
def test_setup_signal_interruption_no_select_poll(self, mock_select):
def test_setup_signal_interruption_no_select_poll(self):
# NOTE(claudiub): SignalHandler is a singleton, which means that it
# might already be initialized. We need to clear to clear the cache
# in order to prevent race conditions between tests.
service.SignalHandler.__class__._instances.clear()
with mock.patch('eventlet.patcher.original',
return_value=object()) as get_original:
signal_handler = service.SignalHandler()
get_original.assert_called_with('select')
self.addCleanup(service.SignalHandler.__class__._instances.clear)
self.assertFalse(
signal_handler._SignalHandler__force_interrupt_on_signal)
@mock.patch('sys.version_info', (3, 5))
def test_setup_signal_interruption_select_poll(self):
# NOTE(claudiub): SignalHandler is a singleton, which means that it
# might already be initialized. We need to clear to clear the cache
# in order to prevent race conditions between tests.
service.SignalHandler.__class__._instances.clear()
signal_handler = service.SignalHandler()
self.addCleanup(service.SignalHandler.__class__._instances.clear)
self.assertFalse(
self.assertTrue(
signal_handler._SignalHandler__force_interrupt_on_signal)
@mock.patch('signal.alarm')