aboutsummaryrefslogtreecommitdiffstats
path: root/python/gevent/_tracer.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/gevent/_tracer.py')
-rw-r--r--python/gevent/_tracer.py179
1 files changed, 0 insertions, 179 deletions
diff --git a/python/gevent/_tracer.py b/python/gevent/_tracer.py
deleted file mode 100644
index 98307ab..0000000
--- a/python/gevent/_tracer.py
+++ /dev/null
@@ -1,179 +0,0 @@
-# Copyright (c) 2018 gevent. See LICENSE for details.
-# cython: auto_pickle=False,embedsignature=True,always_allow_keywords=False
-from __future__ import print_function, absolute_import, division
-
-import sys
-import traceback
-
-from greenlet import settrace
-from greenlet import getcurrent
-
-from gevent.util import format_run_info
-
-from gevent._compat import perf_counter
-from gevent._util import gmctime
-
-
-__all__ = [
- 'GreenletTracer',
- 'HubSwitchTracer',
- 'MaxSwitchTracer',
-]
-
-# Recall these classes are cython compiled, so
-# class variable declarations are bad.
-
-
-class GreenletTracer(object):
- def __init__(self):
- # A counter, incremented by the greenlet trace function
- # we install on every greenlet switch. This is reset when the
- # periodic monitoring thread runs.
-
- self.greenlet_switch_counter = 0
-
- # The greenlet last switched to.
- self.active_greenlet = None
-
- # The trace function that was previously installed,
- # if any.
- # NOTE: Calling a class instance is cheaper than
- # calling a bound method (at least when compiled with cython)
- # even when it redirects to another function.
- prev_trace = settrace(self)
-
- self.previous_trace_function = prev_trace
-
- self._killed = False
-
- def kill(self):
- # Must be called in the monitored thread.
- if not self._killed:
- self._killed = True
- settrace(self.previous_trace_function)
- self.previous_trace_function = None
-
- def _trace(self, event, args):
- # This function runs in the thread we are monitoring.
- self.greenlet_switch_counter += 1
- if event in ('switch', 'throw'):
- # args is (origin, target). This is the only defined
- # case
- self.active_greenlet = args[1]
- else:
- self.active_greenlet = None
- if self.previous_trace_function is not None:
- self.previous_trace_function(event, args)
-
- def __call__(self, event, args):
- return self._trace(event, args)
-
- def did_block_hub(self, hub):
- # Check to see if we have blocked since the last call to this
- # method. Returns a true value if we blocked (not in the hub),
- # a false value if everything is fine.
-
- # This may be called in the same thread being traced or a
- # different thread; if a different thread, there is a race
- # condition with this being incremented in the thread we're
- # monitoring, but probably not often enough to lead to
- # annoying false positives.
-
- active_greenlet = self.active_greenlet
- did_switch = self.greenlet_switch_counter != 0
- self.greenlet_switch_counter = 0
-
- if did_switch or active_greenlet is None or active_greenlet is hub:
- # Either we switched, or nothing is running (we got a
- # trace event we don't know about or were requested to
- # ignore), or we spent the whole time in the hub, blocked
- # for IO. Nothing to report.
- return False
- return True, active_greenlet
-
- def ignore_current_greenlet_blocking(self):
- # Don't pay attention to the current greenlet.
- self.active_greenlet = None
-
- def monitor_current_greenlet_blocking(self):
- self.active_greenlet = getcurrent()
-
- def did_block_hub_report(self, hub, active_greenlet, format_kwargs):
- report = ['=' * 80,
- '\n%s : Greenlet %s appears to be blocked' %
- (gmctime(), active_greenlet)]
- report.append(" Reported by %s" % (self,))
- try:
- frame = sys._current_frames()[hub.thread_ident]
- except KeyError:
- # The thread holding the hub has died. Perhaps we shouldn't
- # even report this?
- stack = ["Unknown: No thread found for hub %r\n" % (hub,)]
- else:
- stack = traceback.format_stack(frame)
- report.append('Blocked Stack (for thread id %s):' % (hex(hub.thread_ident),))
- report.append(''.join(stack))
- report.append("Info:")
- report.extend(format_run_info(**format_kwargs))
-
- return report
-
-
-class _HubTracer(GreenletTracer):
- def __init__(self, hub, max_blocking_time):
- GreenletTracer.__init__(self)
- self.max_blocking_time = max_blocking_time
- self.hub = hub
-
- def kill(self):
- self.hub = None
- GreenletTracer.kill(self)
-
-
-class HubSwitchTracer(_HubTracer):
- # A greenlet tracer that records the last time we switched *into* the hub.
-
- def __init__(self, hub, max_blocking_time):
- _HubTracer.__init__(self, hub, max_blocking_time)
- self.last_entered_hub = 0
-
- def _trace(self, event, args):
- GreenletTracer._trace(self, event, args)
- if self.active_greenlet is self.hub:
- self.last_entered_hub = perf_counter()
-
- def did_block_hub(self, hub):
- if perf_counter() - self.last_entered_hub > self.max_blocking_time:
- return True, self.active_greenlet
-
-
-class MaxSwitchTracer(_HubTracer):
- # A greenlet tracer that records the maximum time between switches,
- # not including time spent in the hub.
-
- def __init__(self, hub, max_blocking_time):
- _HubTracer.__init__(self, hub, max_blocking_time)
- self.last_switch = perf_counter()
- self.max_blocking = 0
-
- def _trace(self, event, args):
- old_active = self.active_greenlet
- GreenletTracer._trace(self, event, args)
- if old_active is not self.hub and old_active is not None:
- # If we're switching out of the hub, the blocking
- # time doesn't count.
- switched_at = perf_counter()
- self.max_blocking = max(self.max_blocking,
- switched_at - self.last_switch)
-
- def did_block_hub(self, hub):
- if self.max_blocking == 0:
- # We never switched. Check the time now
- self.max_blocking = perf_counter() - self.last_switch
-
- if self.max_blocking > self.max_blocking_time:
- return True, self.active_greenlet
-
-
-from gevent._util import import_c_accel
-import_c_accel(globals(), 'gevent.__tracer')