def monitor_memory_usage(self, _hub): max_allowed = GEVENT_CONFIG.max_memory_usage if not max_allowed: # They disabled it. return -1 # value for tests rusage = self._get_process().memory_full_info() # uss only documented available on Windows, Linux, and OS X. # If not available, fall back to rss as an aproximation. mem_usage = getattr(rusage, 'uss', 0) or rusage.rss event = None # Return value for tests if mem_usage > max_allowed: if mem_usage > self._memory_exceeded: # We're still growing event = MemoryUsageThresholdExceeded(mem_usage, max_allowed, rusage) notify(event) self._memory_exceeded = mem_usage else: # we're below. Were we above it last time? if self._memory_exceeded: event = MemoryUsageUnderThreshold(mem_usage, max_allowed, rusage, self._memory_exceeded) notify(event) self._memory_exceeded = 0 return event
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 did_block = self._greenlet_tracer.did_block_hub(hub) if not did_block: return active_greenlet = did_block[1] report = self._greenlet_tracer.did_block_hub_report( hub, active_greenlet, dict(greenlet_stacks=False, current_thread_ident=self.monitor_thread_ident)) 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 monitor_memory_usage(self, _hub): max_allowed = GEVENT_CONFIG.max_memory_usage if not max_allowed: # They disabled it. return -1 # value for tests rusage = self._get_process().memory_full_info() # uss only documented available on Windows, Linux, and OS X. # If not available, fall back to rss as an aproximation. mem_usage = getattr(rusage, 'uss', 0) or rusage.rss event = None # Return value for tests if mem_usage > max_allowed: if mem_usage > self._memory_exceeded: # We're still growing event = MemoryUsageThresholdExceeded( mem_usage, max_allowed, rusage) notify(event) self._memory_exceeded = mem_usage else: # we're below. Were we above it last time? if self._memory_exceeded: event = MemoryUsageUnderThreshold( mem_usage, max_allowed, rusage, self._memory_exceeded) notify(event) self._memory_exceeded = 0 return event
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 did_block = self._greenlet_tracer.did_block_hub(hub) if not did_block: return active_greenlet = did_block[1] report = self._greenlet_tracer.did_block_hub_report( hub, active_greenlet, dict(greenlet_stacks=False, current_thread_ident=self.monitor_thread_ident)) 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 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)