80 lines
2.4 KiB
Plaintext
80 lines
2.4 KiB
Plaintext
# Use this file with
|
|
# gdb --batch --return-child-result -x gdb-dump-stack <some command>
|
|
# to get full stack backtraces when the command or any of its
|
|
# children fails.
|
|
|
|
# It is important that we keep processes running in parallel,
|
|
# otherwise we risk deadlocks once multiple processes are involved.
|
|
set non-stop on
|
|
|
|
# Keep track also of child processes.
|
|
set detach-on-fork off
|
|
set follow-fork-mode parent
|
|
|
|
python
|
|
class Exited (gdb.Function):
|
|
"""Return 1 if current threat has exited, else 0."""
|
|
|
|
def __init__ (self):
|
|
super (Exited, self).__init__("exited")
|
|
|
|
def invoke (self):
|
|
thread = gdb.selected_thread()
|
|
if thread is None or thread.is_exited():
|
|
return 1
|
|
else:
|
|
return 0
|
|
|
|
class FindStopped (gdb.Function):
|
|
"""Dump stack backtrace of all stopped threads and continue them."""
|
|
|
|
def __init__ (self):
|
|
super (FindStopped, self).__init__("find_stopped")
|
|
|
|
def invoke (self):
|
|
for inferior in gdb.inferiors():
|
|
if inferior.is_valid():
|
|
for thread in inferior.threads():
|
|
if thread.is_valid() and thread.is_stopped():
|
|
thread.switch()
|
|
return 1
|
|
return 0
|
|
|
|
Exited()
|
|
FindStopped()
|
|
end
|
|
|
|
# Start the command. Returns once something needs our attention.
|
|
run
|
|
|
|
# Continously deal with events that normally require user intervention:
|
|
# - a process was stopped because of something (like a segfault)
|
|
# - a process has quit
|
|
while 1
|
|
if $find_stopped()
|
|
# The stopped thread is now selected, so we can dump some information about
|
|
# it, then continue it.
|
|
info inferiors
|
|
bt
|
|
continue
|
|
else
|
|
inferior 1
|
|
if $exited()
|
|
# No stopped thread, current thread has quit -> we are done.
|
|
loop_break
|
|
else
|
|
# We need to do something, otherwise we would busy-loop
|
|
# while all threads are running. Therefore we interrupt
|
|
# and restart the main thread.
|
|
#
|
|
# In (unlikely?) case that some other thread stops by
|
|
# itself while we do that, we continue all threads to
|
|
# avoid potential deadlocks (main thread running again but
|
|
# waiting for stopped thread that we don't know about).
|
|
# The downside is that we don't print a stack backtrace
|
|
# of such a thread.
|
|
interrupt
|
|
continue -a
|
|
end
|
|
end
|