diff --git a/eventlet/debug.py b/eventlet/debug.py index 50586b3..76528ed 100644 --- a/eventlet/debug.py +++ b/eventlet/debug.py @@ -134,10 +134,23 @@ def tpool_exceptions(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. + behavior in an application. + + It does this by telling the kernel to raise a SIGALARM after a + short timeout, and clearing the timeout every time the hub + greenlet is resumed. Therefore, any code that runs for a long + time without yielding to the hub will get interrupted by the + blocking detector (don't use it in production!). + + The *resolution* argument governs how long the SIGALARM timeout + waits in seconds. If on Python 2.6 or later, the implementation + uses :func:`signal.setitimer` and can be specified as a + floating-point value. On 2.5 or earlier, 1 second is the minimum. + The shorter the resolution, the greater the chance of false + positives. """ from eventlet import hubs + assert resolution > 0 hubs.get_hub().debug_blocking = state hubs.get_hub().debug_blocking_resolution = resolution if(not state): diff --git a/eventlet/hubs/hub.py b/eventlet/hubs/hub.py index 333b3d3..c759d81 100644 --- a/eventlet/hubs/hub.py +++ b/eventlet/hubs/hub.py @@ -1,20 +1,23 @@ import heapq -import sys +import math import traceback -import warnings import signal +import sys +import warnings -HAS_ITIMER = False -alarm_func = signal.alarm +arm_alarm = None if hasattr(signal, 'setitimer'): - HAS_ITIMER = True + def alarm_itimer(seconds): + signal.setitimer(signal.ITIMER_REAL, seconds) + arm_alarm = alarm_itimer else: try: import itimer - HAS_ITIMER = True - alarm_func = itimer.alarm + arm_alarm = itimer.alarm except ImportError: - pass + def alarm_signal(seconds): + signal.alarm(math.ceil(seconds)) + arm_alarm = alarm_signal from eventlet.support import greenlets as greenlet, clear_sys_exc_info from eventlet.hubs import timer @@ -57,7 +60,7 @@ class DebugListener(FdListener): def alarm_handler(signum, frame): import inspect - raise RuntimeError("ALARMED at" + str(inspect.getframeinfo(frame))) + raise RuntimeError("Blocking detector ALARMED at" + str(inspect.getframeinfo(frame))) class BaseHub(object): @@ -91,8 +94,7 @@ class BaseHub(object): if tmp != alarm_handler: self._old_signal_handler = tmp - if HAS_ITIMER: - alarm_func(self.debug_blocking_resolution) + arm_alarm(self.debug_blocking_resolution) def block_detect_post(self): if (hasattr(self, "_old_signal_handler") and