Add a more useful/detailed frame dumping function

When things start behaving badly having access to a more
capable frame dumping function can be pretty handy to gain
more insight into what the greenthreads are doing (and what
the functions and those functions local variables are that
they are currently running with).

This adds such a capability to the pgt() alias function that
the backdoor exposes, the default usage shows the simpler and
less useful print_stack() output but the newer and less simple
output can be enabled by calling pgt(False).

Doing so will produce output like:

https://gist.github.com/harlowja/b91b512dcf1b6db592bb

Change-Id: Ifc77b908699b911f60f039ac54f98391a7e53732
This commit is contained in:
Joshua Harlow 2016-02-03 12:56:23 -08:00
parent bfc8600b09
commit 81cc23f306
1 changed files with 42 additions and 2 deletions

View File

@ -48,14 +48,54 @@ def _dont_use_this():
print("Don't use this, just disconnect instead")
def _dump_frame(f, frame_chapter):
co = f.f_code
print(" %s Frame: %s" % (frame_chapter, co.co_name))
print(" File: %s" % (co.co_filename))
print(" Captured at line number: %s" % (f.f_lineno))
co_locals = set(co.co_varnames)
if len(co_locals):
not_set = co_locals.copy()
set_locals = {}
for var_name in f.f_locals.keys():
if var_name in co_locals:
set_locals[var_name] = f.f_locals[var_name]
not_set.discard(var_name)
if set_locals:
print(" %s set local variables:" % (len(set_locals)))
for var_name in sorted(set_locals.keys()):
print(" %s => %r" % (var_name, f.f_locals[var_name]))
else:
print(" 0 set local variables.")
if not_set:
print(" %s not set local variables:" % (len(not_set)))
for var_name in sorted(not_set):
print(" %s" % (var_name))
else:
print(" 0 not set local variables.")
else:
print(" 0 Local variables.")
def _detailed_dump_frames(f, thread_index):
i = 0
while f is not None:
_dump_frame(f, "%s.%s" % (thread_index, i + 1))
f = f.f_back
i += 1
def _find_objects(t):
return [o for o in gc.get_objects() if isinstance(o, t)]
def _print_greenthreads():
def _print_greenthreads(simple=True):
for i, gt in enumerate(_find_objects(greenlet.greenlet)):
print(i, gt)
traceback.print_stack(gt.gr_frame)
if simple:
traceback.print_stack(gt.gr_frame)
else:
_detailed_dump_frames(gt.gr_frame, i)
print()