Add support for the itimer module with blocking detection
This will allow for subsecond blocking detection thanks to the itimer module recently released by Slide, Inc: http://github.com/slideinc/itimer
This commit is contained in:
@@ -132,13 +132,14 @@ def tpool_exceptions(state = False):
|
||||
from eventlet import tpool
|
||||
tpool.QUIET = not state
|
||||
|
||||
def hub_blocking_detection(state = False):
|
||||
def hub_blocking_detection(state = False, resolution = 1):
|
||||
"""Toggles whether Eventlet makes an effort to detect blocking
|
||||
behavior in other code. It does this by setting a SIGALARM with a short
|
||||
timeout.
|
||||
"""
|
||||
from eventlet import hubs
|
||||
hubs.get_hub().debug_blocking = state
|
||||
hubs.get_hub().debug_blocking_resolution = resolution
|
||||
if(not state):
|
||||
hubs.get_hub().block_detect_post()
|
||||
|
||||
|
@@ -4,6 +4,13 @@ import traceback
|
||||
import warnings
|
||||
import signal
|
||||
|
||||
HAS_ITIMER = False
|
||||
try:
|
||||
import itimer
|
||||
HAS_ITIMER = True
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
from eventlet.support import greenlets as greenlet, clear_sys_exc_info
|
||||
from eventlet.hubs import timer
|
||||
from eventlet import patcher
|
||||
@@ -71,13 +78,19 @@ class BaseHub(object):
|
||||
self.timers_canceled = 0
|
||||
self.debug_exceptions = True
|
||||
self.debug_blocking = False
|
||||
self.debug_blocking_resolution = 1
|
||||
|
||||
def block_detect_pre(self):
|
||||
# shortest alarm we can possibly raise is one second
|
||||
tmp = signal.signal(signal.SIGALRM, alarm_handler)
|
||||
if tmp != alarm_handler:
|
||||
self._old_signal_handler = tmp
|
||||
signal.alarm(1)
|
||||
|
||||
if HAS_ITIMER:
|
||||
itimer.alarm(self.debug_blocking_resolution)
|
||||
else:
|
||||
signal.alarm(self.debug_blocking_resolution)
|
||||
|
||||
def block_detect_post(self):
|
||||
if (hasattr(self, "_old_signal_handler") and
|
||||
self._old_signal_handler):
|
||||
|
@@ -92,6 +92,16 @@ def skip_on_windows(func):
|
||||
import sys
|
||||
return skip_if(sys.platform.startswith('win'))(func)
|
||||
|
||||
def skip_if_no_itimer(func):
|
||||
""" Decorator that skips a test if the `itimer` module isn't found """
|
||||
has_itimer = False
|
||||
try:
|
||||
import itimer
|
||||
has_itimer = True
|
||||
except ImportError:
|
||||
pass
|
||||
return skip_unless(has_itimer)(func)
|
||||
|
||||
|
||||
class TestIsTakingTooLong(Exception):
|
||||
""" Custom exception class to be raised when a test's runtime exceeds a limit. """
|
||||
|
@@ -1,4 +1,4 @@
|
||||
from tests import LimitedTestCase, main, skip_with_pyevent
|
||||
from tests import LimitedTestCase, main, skip_with_pyevent, skip_if_no_itimer
|
||||
import time
|
||||
import eventlet
|
||||
from eventlet import hubs
|
||||
@@ -154,6 +154,18 @@ class TestHubBlockingDetector(LimitedTestCase):
|
||||
self.assertRaises(RuntimeError, gt.wait)
|
||||
debug.hub_blocking_detection(False)
|
||||
|
||||
@skip_if_no_itimer
|
||||
def test_block_detect_with_itimer(self):
|
||||
def look_im_blocking():
|
||||
import time
|
||||
time.sleep(0.5)
|
||||
|
||||
from eventlet import debug
|
||||
debug.hub_blocking_detection(True, resolution=0.1)
|
||||
gt = eventlet.spawn(look_im_blocking)
|
||||
self.assertRaises(RuntimeError, gt.wait)
|
||||
debug.hub_blocking_detection(False)
|
||||
|
||||
class TestSuspend(LimitedTestCase):
|
||||
TEST_TIMEOUT=3
|
||||
def test_suspend_doesnt_crash(self):
|
||||
|
Reference in New Issue
Block a user