def did_block_hub_report(self, hub, active_greenlet, format_kwargs): # XXX: On Python 2 with greenlet 1.0a1, '%s' formatting a greenlet # results in a unicode object. This is a bug in greenlet, I think. # https://github.com/python-greenlet/greenlet/issues/218 report = [ '=' * 80, '\n%s : Greenlet %s appears to be blocked' % (gmctime(), str(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
def _on_expiration(self, prev_greenlet, ex): from gevent.util import format_run_info loop = gevent.get_hub().loop debug_info = 'N/A' if hasattr(loop, 'debug'): debug_info = [str(s) for s in loop.debug()] run_info = format_run_info() self._expire_info = 'Loop Debug:\n%s\nRun Info:\n%s' % ( '\n'.join(debug_info), '\n'.join(run_info)) gevent.Timeout._on_expiration(self, prev_greenlet, ex)
def monitor_blocking(self, hub): # Called periodically to see if the trace function has # fired to switch greenlets. If not, we will print # the greenlet tree. # For tests, we return a true value when we think we found something # blocking # 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 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(greenlet_stacks=False, current_thread_ident=self.monitor_thread_ident)) report.append(report[0]) stream = hub.exception_stream for line in report: # Printing line by line may interleave with other things, # but it should also prevent a "reentrant call to print" # when the report is large. print(line, file=stream) notify( EventLoopBlocked(active_greenlet, GEVENT_CONFIG.max_blocking_time, report)) return (active_greenlet, report)
def test_basic(self): lines = util.format_run_info() value = '\n'.join(lines) self.assertIn('Threads', value) self.assertIn('Greenlets', value) # because it's a raw greenlet, we have no data for it. self.assertNotIn("Spawned at", value) self.assertNotIn("Parent greenlet", value) self.assertNotIn("Spawn Tree Locals", value)
def idle_watcher(): return logger = get_logger() prev = None while True: idle() current = format_run_info() if prev != current: prev = current logger.warning("\n".join(current)) sleep(0.01)
def test_greenlet_class(self): from greenlet import getcurrent from gevent.threadpool import _WorkerGreenlet worker_greenlet = self.pool.apply(getcurrent) self.assertIsInstance(worker_greenlet, _WorkerGreenlet) r = repr(worker_greenlet) self.assertIn('ThreadPoolWorker', r) self.assertIn('thread_ident', r) self.assertIn('hub=', r) from gevent.util import format_run_info info = '\n'.join(format_run_info()) self.assertIn("<ThreadPoolWorker", info)
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
def _on_expiration(self, prev_greenlet, ex): from gevent.util import format_run_info self._expire_info = '\n'.join(format_run_info()) gevent.Timeout._on_expiration(self, prev_greenlet, ex)