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:
R. Tyler Ballance
2010-06-24 13:47:38 -07:00
parent acfd78d7d9
commit cf523d957e
4 changed files with 39 additions and 3 deletions

View File

@@ -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()

View File

@@ -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):

View File

@@ -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. """

View File

@@ -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):