Fix blocking detector for cases that don't have the itimer module installed.
This commit is contained in:
@@ -134,10 +134,23 @@ def tpool_exceptions(state = False):
|
|||||||
|
|
||||||
def hub_blocking_detection(state = False, resolution = 1):
|
def hub_blocking_detection(state = False, resolution = 1):
|
||||||
"""Toggles whether Eventlet makes an effort to detect blocking
|
"""Toggles whether Eventlet makes an effort to detect blocking
|
||||||
behavior in other code. It does this by setting a SIGALARM with a short
|
behavior in an application.
|
||||||
timeout.
|
|
||||||
|
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
|
from eventlet import hubs
|
||||||
|
assert resolution > 0
|
||||||
hubs.get_hub().debug_blocking = state
|
hubs.get_hub().debug_blocking = state
|
||||||
hubs.get_hub().debug_blocking_resolution = resolution
|
hubs.get_hub().debug_blocking_resolution = resolution
|
||||||
if(not state):
|
if(not state):
|
||||||
|
|||||||
@@ -1,20 +1,23 @@
|
|||||||
import heapq
|
import heapq
|
||||||
import sys
|
import math
|
||||||
import traceback
|
import traceback
|
||||||
import warnings
|
|
||||||
import signal
|
import signal
|
||||||
|
import sys
|
||||||
|
import warnings
|
||||||
|
|
||||||
HAS_ITIMER = False
|
arm_alarm = None
|
||||||
alarm_func = signal.alarm
|
|
||||||
if hasattr(signal, 'setitimer'):
|
if hasattr(signal, 'setitimer'):
|
||||||
HAS_ITIMER = True
|
def alarm_itimer(seconds):
|
||||||
|
signal.setitimer(signal.ITIMER_REAL, seconds)
|
||||||
|
arm_alarm = alarm_itimer
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
import itimer
|
import itimer
|
||||||
HAS_ITIMER = True
|
arm_alarm = itimer.alarm
|
||||||
alarm_func = itimer.alarm
|
|
||||||
except ImportError:
|
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.support import greenlets as greenlet, clear_sys_exc_info
|
||||||
from eventlet.hubs import timer
|
from eventlet.hubs import timer
|
||||||
@@ -57,7 +60,7 @@ class DebugListener(FdListener):
|
|||||||
|
|
||||||
def alarm_handler(signum, frame):
|
def alarm_handler(signum, frame):
|
||||||
import inspect
|
import inspect
|
||||||
raise RuntimeError("ALARMED at" + str(inspect.getframeinfo(frame)))
|
raise RuntimeError("Blocking detector ALARMED at" + str(inspect.getframeinfo(frame)))
|
||||||
|
|
||||||
|
|
||||||
class BaseHub(object):
|
class BaseHub(object):
|
||||||
@@ -91,8 +94,7 @@ class BaseHub(object):
|
|||||||
if tmp != alarm_handler:
|
if tmp != alarm_handler:
|
||||||
self._old_signal_handler = tmp
|
self._old_signal_handler = tmp
|
||||||
|
|
||||||
if HAS_ITIMER:
|
arm_alarm(self.debug_blocking_resolution)
|
||||||
alarm_func(self.debug_blocking_resolution)
|
|
||||||
|
|
||||||
def block_detect_post(self):
|
def block_detect_post(self):
|
||||||
if (hasattr(self, "_old_signal_handler") and
|
if (hasattr(self, "_old_signal_handler") and
|
||||||
|
|||||||
Reference in New Issue
Block a user