Probably horribly broken block detecter, only for poll/epoll hubs.
This commit is contained in:
@@ -130,3 +130,14 @@ def tpool_exceptions(state = False):
|
||||
it normally does."""
|
||||
from eventlet import tpool
|
||||
tpool.QUIET = not state
|
||||
|
||||
def hub_blocking_detection(state = False):
|
||||
"""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
|
||||
if(not state):
|
||||
hubs.get_hub().block_detect_post()
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import heapq
|
||||
import sys
|
||||
import traceback
|
||||
import warnings
|
||||
import signal
|
||||
|
||||
from eventlet.support import greenlets as greenlet, clear_sys_exc_info
|
||||
from eventlet.hubs import timer
|
||||
@@ -42,6 +43,11 @@ class DebugListener(FdListener):
|
||||
__str__ = __repr__
|
||||
|
||||
|
||||
def alarm_handler(signum, frame):
|
||||
import inspect
|
||||
raise RuntimeError("ALARMED at" + str(inspect.getframeinfo(frame)))
|
||||
|
||||
|
||||
class BaseHub(object):
|
||||
""" Base hub class for easing the implementation of subclasses that are
|
||||
specific to a particular underlying event architecture. """
|
||||
@@ -62,8 +68,21 @@ class BaseHub(object):
|
||||
self.timers = []
|
||||
self.next_timers = []
|
||||
self.lclass = FdListener
|
||||
self.debug_exceptions = True
|
||||
self.timers_canceled = 0
|
||||
self.debug_exceptions = True
|
||||
self.debug_blocking = False
|
||||
|
||||
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)
|
||||
def block_detect_post(self):
|
||||
if (hasattr(self, "_old_signal_handler") and
|
||||
self._old_signal_handler):
|
||||
signal.signal(signal.SIGALRM, self._old_signal_handler)
|
||||
signal.alarm(0)
|
||||
|
||||
def add(self, evtype, fileno, cb):
|
||||
""" Signals an intent to or write a particular file descriptor.
|
||||
@@ -166,7 +185,11 @@ class BaseHub(object):
|
||||
self.stopping = False
|
||||
while not self.stopping:
|
||||
self.prepare_timers()
|
||||
if self.debug_blocking:
|
||||
self.block_detect_pre()
|
||||
self.fire_timers(self.clock())
|
||||
if self.debug_blocking:
|
||||
self.block_detect_post()
|
||||
self.prepare_timers()
|
||||
wakeup_when = self.sleep_until()
|
||||
if wakeup_when is None:
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import sys
|
||||
import errno
|
||||
import signal
|
||||
from eventlet import patcher
|
||||
select = patcher.original('select')
|
||||
time = patcher.original('time')
|
||||
sleep = time.sleep
|
||||
|
||||
from eventlet.support import get_errno, clear_sys_exc_info
|
||||
from eventlet.hubs.hub import BaseHub, READ, WRITE, noop
|
||||
from eventlet.hubs.hub import BaseHub, READ, WRITE, noop, alarm_handler
|
||||
|
||||
EXC_MASK = select.POLLERR | select.POLLHUP
|
||||
READ_MASK = select.POLLIN | select.POLLPRI
|
||||
@@ -82,6 +83,11 @@ class Hub(BaseHub):
|
||||
raise
|
||||
SYSTEM_EXCEPTIONS = self.SYSTEM_EXCEPTIONS
|
||||
|
||||
if self.debug_blocking:
|
||||
# shortest alarm we can possibly set is one second
|
||||
signal.signal(signal.SIGALRM, alarm_handler)
|
||||
signal.alarm(1)
|
||||
|
||||
for fileno, event in presult:
|
||||
try:
|
||||
if event & READ_MASK:
|
||||
@@ -99,3 +105,7 @@ class Hub(BaseHub):
|
||||
except:
|
||||
self.squelch_exception(fileno, sys.exc_info())
|
||||
clear_sys_exc_info()
|
||||
|
||||
if self.debug_blocking:
|
||||
signal.alarm(0)
|
||||
|
||||
|
||||
@@ -142,6 +142,17 @@ class TestHubSelection(LimitedTestCase):
|
||||
hubs._threadlocal.hub = oldhub
|
||||
|
||||
|
||||
class TestHubBlockingDetector(LimitedTestCase):
|
||||
TEST_TIMEOUT = 10
|
||||
def test_block_detect(self):
|
||||
def look_im_blocking():
|
||||
import time
|
||||
time.sleep(2)
|
||||
from eventlet import debug
|
||||
debug.hub_blocking_detection(True)
|
||||
gt = eventlet.spawn(look_im_blocking)
|
||||
self.assertRaises(RuntimeError, gt.wait)
|
||||
debug.hub_blocking_detection(False)
|
||||
|
||||
class Foo(object):
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user