Skip to content

12. Events

There have been many new Python scripting features added to gdb since my last post on the topic.  The one I want to focus on today is event generation.

I wrote a little about events in gdb-python post #9 — but a lot has changed since then.  A Google SoC student, Oguz Kayral, wrote better support for events in 2009.  Then, Sami Wagiaalla substantially rewrote it and put it into gdb.

In the new approach, gdb provides a number of event registries.  An event registry is just an object with connect and disconnect methods.  Your code can use connect to register a callback with a registry; the callback is just any callable object.  The event is passed to the callable as an argument.

Each registry emits specific events — “emitting” an event just means calling all the callables that were connected to the registry.  For example, the registry emits events when an inferior or thread has stopped for some reason.  The event describes the reason for the stop — e.g., a breakpoint was hit, or a signal was delivered.

Here’s a script showing this feature in action.  It arranges for a notification to pop up if your program stops unexpectedly — if your program exits normally, nothing is done.  Something like this could be handy for automating testing under gdb; you could augment it by having gdb automatically exit if fires.  You could also augment it by setting a conditional breakpoint to catch a rarely-seen condition; then just wait for the notification to appear.

To try this out, just “source” it into gdb.  Then, run your program in various ways.

import gdb, threading, Queue, gtk, glib, os, pynotify

(read_pipe, write_pipe) = os.pipe()

event_queue = Queue.Queue()

def send_to_gtk(func):
    os.write(write_pipe, 'x')

def on_stop_event(event):
    n = pynotify.Notification('Your program stopped in gdb')

class GtkThread(threading.Thread):
    def handle_queue(self, source, condition):
        global event_queue, 1)
        func = event_queue.get()

    def run(self):
        global read_pipe
        glib.io_add_watch(read_pipe, glib.IO_IN, self.handle_queue)



t = GtkThread()


  1. Scott Tsai wrote:

    I think you meant to call send_to_gtk(gtk.main_quit) in on_stop_event().

    Saturday, January 7, 2012 at 8:12 am | Permalink
  2. tom wrote:

    Crud, you’re right, I messed that up.

    The idea is that all Gtk code should run in its own thread. I don’t think this is enforced, though, hence my bug.

    What I meant was something like (untested): send_to_gtk(on_stop_event))

    … but with on_stop_event suitably defined not to have arguments.

    Saturday, January 7, 2012 at 10:25 pm | Permalink
  3. sriram adhyapak wrote:

    I am using python 2.6.5 under ubuntu 10.04

    When I place a “ (exit_handler)” in my code

    I get a
    AttributeError: ‘module’ object has no attribute ‘events’

    what am I missing?

    Saturday, February 4, 2012 at 2:17 am | Permalink
  4. tom wrote:

    Your gdb is probably too old. What version are you using?

    Saturday, February 4, 2012 at 2:39 am | Permalink

    I am using GNU gdb (GDB) 7.1-ubuntu

    This GDB was configured as “i486-linux-gnu

    Saturday, February 4, 2012 at 5:43 pm | Permalink
  6. tom wrote:

    Events didn’t go in until 7.3

    Saturday, February 4, 2012 at 8:47 pm | Permalink
  7. sriram adhyapak wrote:

    Thanks TOM! works in 7.4

    Another help needed. Can I use the following in python …
    gdb.execute(‘while (!$myFlagToQuit) \
    python run_one_stepinto() \
    end’,False, True)
    I am checking a python var (viz. myFlagToQuit) and want to run one python function (viz. run_one_stepinto) and end the loop.

    I am setting the var “myFlagToQuit” within an exit handler.

    Sunday, February 5, 2012 at 12:33 am | Permalink
  8. tom wrote:

    Why not just put the entire loop in Python?

    Monday, February 6, 2012 at 2:53 pm | Permalink

Post a Comment

Your email is never published nor shared. Required fields are marked *