我的程序有100个线程,其中大多数是空闲的,并且在空闲时共享一个非常明确的回溯。大多数时候我只对非空闲的线程感兴趣,因此没有“常见”的回溯。我认为使用gdb脚本是一种很好的方法。
define backtraces
thread apply all bt
end
此脚本将只打印所有回溯。有没有办法将此输出存储到变量中,然后我可以处理,修剪并仅显示相关的回溯?
我天真地试过:
define backtraces
set $bts = thread apply all bt
// do whatever processing here
end
但是按照预期的那样失败了:
当前上下文中没有符号“thread”。
有更好的方法吗?或者关于如何在gdb中为脚本提供动力的好教程?
答案 0 :(得分:2)
答案 1 :(得分:1)
使用Employed Russian的回答中的链接,我得到了一些工作。这是后人,因为它完全不明显。
import gdb
# This loops through all the Thread objects in the process
for thread in gdb.selected_inferior().threads():
# This is equivalent to 'thread X'
thread.switch()
print "Thread %s" % thread.num
# Just execute a raw gdb command
gdb.execute('bt')
framesNames = []
f = gdb.newest_frame()
while f is not None:
framesNames.append(gdb.Frame.name(f))
f = gdb.Frame.older(f)
# do something with the name of each frame
如果这是在一个名为traces.py
的文件中,那么从gdb中你可以执行python:
source traces.py
还有其他方法可以调用此python脚本。
答案 2 :(得分:0)
这是我根据JaredC得出的结论:
import gdb
class FilteredThreadBacktraceCommand(gdb.Command):
"""
Implements a command that allows printing the backtrace only for threads
that do not have given frames.
The class must be instantiated with a list of the frames to ignore. If the
stack for a thread has any of those frames then the stack for that thread
will not be printed (a visual dot will be printed to show a thread was just
ignored and provide a notion of progress).
"""
def __init__(self, ignored_frames):
super (FilteredThreadBacktraceCommand, self).__init__ ("fbt", gdb.COMMAND_STACK)
self.ignored_frames = ignored_frames
def invoke(self, arg, from_tty):
args = gdb.string_to_argv(arg)
if len(args) != 0:
gdb.write("ERROR: invalid number of arguments.\n")
return
# This loops through all the Thread objects in the process
for thread in gdb.selected_inferior().threads():
# This is equivalent to 'thread X'
thread.switch()
f = gdb.newest_frame()
frames = []
invalid_thread = False
while f is not None:
if any(ignored_frame in f.name() for ignored_frame in self.ignored_frames):
invalid_thread = True
break
frames.append(f)
f = gdb.Frame.older(f)
if invalid_thread:
# Visual effect as iterating frames might take a while
sys.stdout.write('.')
sys.stdout.flush()
continue
print "\nThread %s:" % thread.num
for i in range(len(frames)):
f = frames[i]
funcInfo = f.function()
printStr = "#{} in {}".format(i, f.name())
if f.function():
printStr += " at {}:{}".format(funcInfo.symtab.filename, funcInfo.line)
else:
printStr += " at (???)"
print(printStr)
FilteredThreadBacktraceCommand(["os::PlatformEvent::park"])
您可以在创建时向类提供要忽略的框架。也可以使用这种通用名称,以便为要注册的命令提供一个名称,以便您可以使用不同的过滤来使用不同的命令。