Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Continue after SIGNAL with a python script in gdb

Tags:

python

gdb

I am trying to generate some output on segmentation faults (and other signals) with a python script in gdb. The script looks like this:

import gdb

def event_handler(event):
    gdb.execute("set scheduler-locking on") # this is needed to avoid parallel exec of the handler

    gdb.write("\n[ME] SIG " + event.stop_signal)
    frame = gdb.selected_frame()
    while frame:
        gdb.write("\n[ME] FN " + str(frame.name()))
        frame = frame.older()

# make sure output goes to a file
gdb.execute("set logging on") 
gdb.execute("set logging file gdbout")
gdb.events.stop.connect(event_handler)

The problem is that I need to press c and Enter on every segmentation fault, the script does not continue.

If I do

gdb.execute("continue")

in the handler, I get a StackOverflow. I think this is because execute() never returns. If I do

handle SIGSEGV nostop

My handler is not invoked any longer. How can I continue after the handler?

like image 360
Alex Avatar asked Aug 20 '14 17:08

Alex


1 Answers

Okay, I found out how to do it:

First, I need a callable for the continue command. As suggested by Tom, this will be used with post_event:

class Executor:
    def __init__(self, cmd):
        self.__cmd = cmd

    def __call__(self):
        gdb.execute(self.__cmd)

And here is the event handler:

def event_handler(event):
    gdb.execute("set scheduler-locking on") # to avoid parallel signals in other threads

    gdb.write("\n[ME] SIG " + event.stop_signal)
    frame = gdb.selected_frame()
    while frame:
        gdb.write("\n[ME] FN " + str(frame.name()))
        frame = frame.older()
    gdb.execute("set scheduler-locking off") # otherwise just this thread is continued, leading to a deadlock   
    gdb.post_event(Executor("continue")) # and post the continue command to gdb

And then, to invoke it:

gdb.execute("set logging on")
gdb.execute("set logging file gdbout")
gdb.execute("set pagination off")
gdb.events.stop.connect(event_handler)

The trick is to disable scheduler-locking later, it is needed to avoid concurrency problems, but it leads to a deadlock if no handler is running.

like image 82
Alex Avatar answered Sep 21 '22 04:09

Alex