public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: sami wagiaalla <swagiaal@redhat.com>
To: gdb-patches@sourceware.org
Subject: Re: [patch] Support inferior events in python
Date: Mon, 17 Jan 2011 22:59:00 -0000	[thread overview]
Message-ID: <4D34AF3F.4090006@redhat.com> (raw)
In-Reply-To: <m3d3oczb0t.fsf@fleche.redhat.com>

[-- Attachment #1: Type: text/plain, Size: 6050 bytes --]

This patch contains changes requested by Eli and Tom, and includes 
documentation for the new features.

> Instead of evregpy_get_nlisteners checking the list size, I think it
> would be better to have "evregpy_any_listeners_p" return a boolean, and
> then check whether the list is empty.  This may be more efficient and is
> what you want to do anyhow.
>

How about evregpy_no_listeners_p ? Fits better with the way the code was 
written.

> Sami>  +event_object *
> Sami>  +create_event_object (PyTypeObject *py_type)
> Sami>  +{
> Sami>  +  event_object *event_obj;
> Sami>  +
> Sami>  +  event_obj = PyObject_New (event_object, py_type);
> Sami>  +  if (!event_obj)
> Sami>  +    goto fail;
> Sami>  +
> Sami>  +  event_obj->dict = PyDict_New ();
> Sami>  +  if (!event_obj->dict)
> Sami>  +    goto fail;
> Sami>  +
> Sami>  +  return event_obj;
> Sami>  +
> Sami>  + fail:
> Sami>  +  Py_XDECREF (event_obj);
> Sami>  +  Py_XDECREF (event_obj->dict);
>
> Won't decrefing event_obj automatically free the dict when needed?
> I didn't look closely but maybe other create_* functions have this issue.
>

I fixed all the create_* functions and made sure the dealloc functions 
are using Py_XDECREF.

> Sami>  +static int
> Sami>  +add_new_registry (eventregistry_object **registryp, char *name)
> Sami>  +{
> Sami>  +  *registryp = create_eventregistry_object ();
> Sami>  +  if(*registryp == NULL)
>
> Newline between these lines.
> Space before open paren.
>
> Why not just return the new registry, or NULL on error?
> That would be simpler.
>

Adding the registry, and doing the needed error checking here, makes the 
calling code simpler. The calling code is what will be extended in 
future development.

>
> Sami>  +static void
> Sami>  +python_inferior_exit (struct inferior *inf)
> Sami>  +{
> Sami>  +  struct cleanup *cleanup;
> Sami>  +  LONGEST exitcode_val;
> Sami>  +  LONGEST *exit_code;
> Sami>  +
> Sami>  +  cleanup = ensure_python_env (get_current_arch (), current_language);
> Sami>  +
> Sami>  +  if (get_internalvar_integer (lookup_internalvar ("_exitcode"),&exitcode_val))
> Sami>  +    exit_code =&exitcode_val;
> Sami>  +
> Sami>  +  if (exit_code
> Sami>  +&&  emit_exited_event (exit_code)<  0)
>
> You have to initialize exit_code to NULL for this to work properly.
>

Done.

> However, I think this is pretty ugly.
> It seems like there should be a better way to get this than looking up
> a convenience variable.
>

Hmm I looked through the code to find another way but could not. 
handle_inferior_event which sets the convenience variable uses 
execution_control_state which I don't have access to.

> I think we need an event representing a thread exit.
> It is ok by me if this comes in a separate patch.
> (FWIW I have a few new events on my branch; I'll update those once this
> patch goes in.)
>

In the original patch this event was halfway between thread exit and 
inferior exit. So I decided to make it inferior exit with the intention 
on adding thread exited/created events in a future patch.

> Sami>  +  signal_event_obj->stop_signal =
> Sami>  +      (PyStringObject *) PyString_FromString (stop_signal);
>
> It is more usual to just use PyObject* everywhere, and not cast to the
> more specific types.
>
> This change should let you eliminate other casts in the patch.
>

Done. I also, updated breakpoint_event_object. I was going with the 
oposite mindset of keeping the type information until a cast is required.

> Sami>  +stop_event_object *
> Sami>  +create_stop_event_object (PyTypeObject *py_type, thread_object *thread)
> Sami>  +{
> Sami>  +  stop_event_object *stop_event_obj =
> Sami>  +      (stop_event_object *) create_event_object (py_type);
> Sami>  +
> Sami>  +  if (!stop_event_obj)
> Sami>  +    goto fail;
> Sami>  +
> Sami>  +  stop_event_obj->inferior_thread = (PyObject *) thread;
> Sami>  +
> Sami>  +  if (evpy_add_attribute ((event_object *) stop_event_obj,
> Sami>  +                          "inferior_thread",
> Sami>  +                          stop_event_obj->inferior_thread)<  0)
> Sami>  +    goto fail;
> Sami>  +
> Sami>  +
> Sami>  +  return stop_event_obj;
>
> I think it would be better to just have one cast at the end, instead of
> lots of casts in the body.
>

Hmm if I change stop_event_object* to event_object it would eliminate 
two casts but also add two. One when setting the inferior thread and one 
for returning. Same goes for all the create_* functions or should I 
change all of those to return more generic objects ?

> Sami>  +  if (bs&&  bs->breakpoint_at
> Sami>  +&&  bs->breakpoint_at->type == bp_breakpoint)
> Sami>  +    {
> Sami>  +      if (evregpy_get_nlisteners (gdb_py_events.breakpoint) == 0)
> Sami>  +	return 0;
>
> I think the short-circuiting logic should be hoisted to the top of the
> function.  This is more efficient and also lets you avoid having to
> deal with reference counting problems involving objects made earlier.
>

I moved the thread creation after the short circuiting, but I cannot be 
moved up further because we have to figure out the type of event.

> Sami>  +  /* Check if the signal is "Signal 0" or "Trace/breakpoint trap".  */
> Sami>  +  if ((strcmp (stop_signal, "0") != 0)
> Sami>  +&&  (strcmp (stop_signal, "SIGTRAP") != 0))
>
> I didn't look this up, but this seems questionable.
> Is this really how this is done?
>

I improved this by using enum target_signal and target_signal_to_name to 
convert the signal to a string when notifying python listeners. That 
looks OK IMO, but we can also create a module gdb.signal, create a pyhon 
Signal type, add Signal types for all signals to gdb.signal, and use a 
Signal object to notify python listeners.


> Sami>  +typedef struct
> Sami>  +{
> Sami>  +  PyObject *inferior_thread;
> Sami>  +  event_object event;
> Sami>  +} stop_event_object;
>
> For the inheritance scheme to work, the 'event' field has to come first.
> I didn't audit the other event object types, but please make sure they
> are all correct.
>

Corrected and checked other objects.



[-- Attachment #2: oguz-python-events.patch --]
[-- Type: text/x-patch, Size: 64018 bytes --]

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 002f3d2..7e80dd4 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,31 @@
+2010-12-22  Sami Wagiaalla  <swagiaal@redhat.com>
+                Oguz Kayral <oguzkayral@gmail.com>
+
+	* python/py-inferior.c (python_on_normal_stop): New function.
+	(python_on_resume): New function.
+	(python_inferior_exit): New function.
+	(gdbpy_initialize_inferior): Add normal_stop, target_resumed, and
+	inferior_exit observers.
+	* python/py-eventregistry.c: New file.
+	* python/py-event.c: New file.
+	* python/py-events.c: New file.
+	* python/py-continueevent.c: New file.
+	* python/py-breakpointevent.c : New file.
+	* python/py-signalevent.c : New file.
+	* python/py-exetiedevent.c : New file.
+	* python/py-breakpoint.c (gdbpy_breakpoint_from_bpstats): New function.
+	Move struct breakpoint_object from here...
+	* python/python-internal.h: ... to here.
+	* python/py-event.h: New file.
+	* python/py-events.h: New file.
+	* Makefile.in (SUBDIR_PYTHON_OBS): Add py-breakpointstopevent.o,
+	py-continueevent.o, py-event.o, py-eventregistry.o, py-events.o,
+	py-exitedevent.o, py-signalstopevent.o, and py-stopevent.o.
+	(SUBDIR_PYTHON_SRCS): Add py-breakpointstopevent.c,
+	py-continueevent.c, py-event.c, py-eventregistry.c, py-events.c,
+	py-exitedevent.c, py-signalstopevent.c, and py-stopevent.c.
+	Add build rules for all the above.
+
 2010-12-14  Ken Werner  <ken.werner@de.ibm.com>
 
 	* valops.c (value_one): Use get_array_bounds to compute the number
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index ff10039..ec309ff 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -272,8 +272,14 @@ SUBDIR_PYTHON_OBS = \
 	python.o \
 	py-auto-load.o \
 	py-block.o \
+	py-bpevent.o \
 	py-breakpoint.o \
 	py-cmd.o \
+	py-continueevent.o \
+	py-event.o \
+	py-evtregistry.o \
+	py-evts.o \
+	py-exitedevent.o \
 	py-frame.o \
 	py-function.o \
 	py-inferior.o \
@@ -283,17 +289,26 @@ SUBDIR_PYTHON_OBS = \
 	py-param.o \
 	py-prettyprint.o \
 	py-progspace.o \
+	py-signalevent.o \
+	py-stopevent.o \
 	py-symbol.o \
 	py-symtab.o \
 	py-type.o \
 	py-utils.o \
 	py-value.o
+
 SUBDIR_PYTHON_SRCS = \
 	python/python.c \
 	python/py-auto-load.c \
 	python/py-block.c \
+	python/py-bpevent.c \
 	python/py-breakpoint.c \
 	python/py-cmd.c \
+	python/py-continueevent.c \
+	python/py-event.c \
+	python/py-evtregistry.c \
+	python/py-evts.c \
+	python/py-exitedevent.c \
 	python/py-frame.c \
 	python/py-function.c \
 	python/py-inferior.c \
@@ -303,6 +318,8 @@ SUBDIR_PYTHON_SRCS = \
 	python/py-param.c \
 	python/py-prettyprint.c \
 	python/py-progspace.c \
+	python/py-signalevent.c \
+	python/py-stopevent.c \
 	python/py-symbol.c \
 	python/py-symtab.c \
 	python/py-type.c \
@@ -1992,6 +2009,10 @@ py-block.o: $(srcdir)/python/py-block.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-block.c
 	$(POSTCOMPILE)
 
+py-bpevent.o: $(srcdir)/python/py-bpevent.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-bpevent.c
+	$(POSTCOMPILE)
+
 py-breakpoint.o: $(srcdir)/python/py-breakpoint.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-breakpoint.c
 	$(POSTCOMPILE)
@@ -2000,6 +2021,26 @@ py-cmd.o: $(srcdir)/python/py-cmd.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-cmd.c
 	$(POSTCOMPILE)
 
+py-continueevent.o: $(srcdir)/python/py-continueevent.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-continueevent.c
+	$(POSTCOMPILE)
+
+py-event.o: $(srcdir)/python/py-event.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-event.c
+	$(POSTCOMPILE)
+
+py-evtregistry.o: $(srcdir)/python/py-evtregistry.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-evtregistry.c
+	$(POSTCOMPILE)
+
+py-evts.o: $(srcdir)/python/py-evts.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-evts.c
+	$(POSTCOMPILE)
+
+py-exitedevent.o: $(srcdir)/python/py-exitedevent.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-exitedevent.c
+	$(POSTCOMPILE)
+
 py-frame.o: $(srcdir)/python/py-frame.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-frame.c
 	$(POSTCOMPILE)
@@ -2036,6 +2077,14 @@ py-progspace.o: $(srcdir)/python/py-progspace.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-progspace.c
 	$(POSTCOMPILE)
 
+py-signalevent.o: $(srcdir)/python/py-signalevent.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-signalevent.c
+	$(POSTCOMPILE)
+
+py-stopevent.o: $(srcdir)/python/py-stopevent.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-stopevent.c
+	$(POSTCOMPILE)
+
 py-symbol.o: $(srcdir)/python/py-symbol.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-symbol.c
 	$(POSTCOMPILE)
diff --git a/gdb/NEWS b/gdb/NEWS
index 559609b..a51740e 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,15 @@
 
 *** Changes since GDB 7.2
 
+* Python Support for Inferior events.
+  Python scripts can add observers to be notified of events
+  occurring the in process being debugged.
+  The following events are currently supported:
+  - gdb.events.breakpoint Breakpoint hit event.
+  - gdb.events.cont Continue event.
+  - gdb.events.signal Signal received event.
+  - gdb.events.exited Inferior exited event.
+
 * New command line options
 
 -data-directory DIR	Specify DIR as the "data-directory".
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index dc9630a..31dea4c 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -20700,6 +20700,7 @@ situation, a Python @code{KeyboardInterrupt} exception is thrown.
 * Selecting Pretty-Printers::   How GDB chooses a pretty-printer.
 * Writing a Pretty-Printer::    Writing a Pretty-Printer.
 * Inferiors In Python::         Python representation of inferiors (processes)
+* Inferior Events In Python::   Listening for events from the process being debugged.
 * Threads In Python::           Accessing inferior threads from Python.
 * Commands In Python::          Implementing new commands in Python.
 * Parameters In Python::        Adding new @value{GDBN} parameters.
@@ -21863,6 +21864,70 @@ the pattern could not be found.
 @end defmethod
 @end table
 
+@node Inferior Events In Python
+@subsubsection Inferior Events In Python
+@cindex inferior events in python
+
+The Python API allows scripts to listen for events coming from the inferior process
+and its threads. In order to listen for events the script must register an observer
+by connecting it to the appropriate event registry. Event registries can be accessed
+through the @code{gdb.events} module.
+
+Here is an example:
+
+@smallexample
+def exit_handler (event):
+    if (isinstance (event, gdb.ExitedEvent)):
+        print "event type: exit"
+        print "exit code: %d" % (event.exit_code)
+
+gdb.events.exited.connect (exit_handler)
+@end smallexample
+
+The following is a listing of the event registries that are available and details
+of the events they emit:
+
+@table @code
+@item events.breakpoint
+@item events.cont
+@item events.exited
+@item events.signal
+@end table
+
+These registries emit the following events in respective order:
+
+@table @code
+@item events.BreakpointEvent
+Indicates that a breakpoint was hit and has the following attributes
+@defivar BreakpointEvent breakpoint
+Reference to the breakpoint of type @code{gdb.Breakpoint} that was hit.
+@xref{Breakpoints In Python}, for details of the @code{gdb.Breakpoint}
+object.
+@end defivar
+@defivar BreakpointEvent inferior_thread
+In non-stop mode breakpoints only stop the thread that has hit them. If
+@value{GDBN} is running in non-stop mode this attribute will hold a reference
+to the thread that has stopped. This object will be of type @code{gdb.InferiorThread}
+@xref{Threads In Python}, for details of the @code{gdb.Breakpoint} object.
+If all threads are stopped the value of this attribute will be @code{None}.
+@end defivar
+@item events.ContinueEvent
+Indicates that the inferior has been continued.
+@item events.ExitedEvent
+Indicates that the inferior has exited.
+@defivar ExitedEvent exit_code
+The exit code that the inferior has returned.
+@end defivar
+@item events.SignalEvent
+@defivar SignalEvent inferior_thread
+In non-stop mode this attribute will be set to the specific thread that received the signal
+and @code{None} otherwise.
+@end defivar
+@defivar SignalEvent stop_signal
+The signal received by the inferior
+@end defivar
+@end table
+
 @node Threads In Python
 @subsubsection Threads In Python
 @cindex threads in python
@@ -23256,10 +23321,31 @@ top of the source tree to the source search path.
 @value{GDBN} comes with a module to assist writing Python code.
 
 @menu
+* gdb.events::         Registering observers to listen to inferior events.
 * gdb.printing::       Building and registering pretty-printers.
 * gdb.types::          Utilities for working with types.
 @end menu
 
+@node gdb.events
+@subsubsection gdb.events
+@cindex gdb.events
+
+This module provides access to inferior event registries. Add observers
+to these registries to receive notification about inferior events.
+
+The available registries are:
+
+@table @code
+@item events.breakpoint
+Notifies listeners of breakpoints being hit.
+@item events.cont
+Notifies listeners whenever the inferior, or one of its threads, is continued.
+@item events.exited
+Notifies listeners when the inferior exits.
+@item events.signal
+Notifies listeners of the inferior, or one of its threads,receiving a signal.
+@end table
+
 @node gdb.printing
 @subsubsection gdb.printing
 @cindex gdb.printing
diff --git a/gdb/python/py-bpevent.c b/gdb/python/py-bpevent.c
new file mode 100644
index 0000000..7dbef53
--- /dev/null
+++ b/gdb/python/py-bpevent.c
@@ -0,0 +1,65 @@
+/* Python interface to inferior breakpoint stop events.
+
+   Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "py-stopevent.h"
+
+static PyTypeObject breakpoint_event_object_type;
+
+static void
+breakpoint_evpy_dealloc (PyObject *self)
+{
+  Py_XDECREF (((breakpoint_event_object *) self)->breakpoint);
+  stop_evpy_dealloc (self);
+}
+
+/* Create and initialize a BreakpointEvent object.  */
+
+breakpoint_event_object *
+create_breakpoint_event_object (struct bpstats *bs,
+                                PyObject *stopped_thread)
+{
+  breakpoint_event_object *breakpoint_event_obj =
+      (breakpoint_event_object *)
+      create_stop_event_object (&breakpoint_event_object_type,
+                                stopped_thread);
+
+  if (!breakpoint_event_obj)
+    goto fail;
+
+  breakpoint_event_obj->breakpoint = gdbpy_breakpoint_from_bpstats (bs);
+  Py_INCREF (breakpoint_event_obj->breakpoint);
+
+  if (evpy_add_attribute ((event_object *) breakpoint_event_obj,
+                          "breakpoint",
+                          breakpoint_event_obj->breakpoint) < 0)
+    goto fail;
+
+  return breakpoint_event_obj;
+
+ fail:
+  Py_XDECREF (breakpoint_event_obj);
+  return NULL;
+}
+
+GDBPY_NEW_EVENT_TYPE (breakpoint,
+                      "gdb.BreakpointEvent",
+                      "BreakpointEvent",
+                      "GDB breakpoint stop event object",
+                      stop_event_object_type,
+                      static);
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index 88d9930..35203e4 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -29,9 +29,6 @@
 #include "cli/cli-script.h"
 #include "ada-lang.h"
 
-/* From breakpoint.c.  */
-typedef struct breakpoint_object breakpoint_object;
-
 static PyTypeObject breakpoint_object_type;
 
 /* Number of live breakpoints.  */
@@ -283,6 +280,15 @@ bppy_set_task (PyObject *self, PyObject *newvalue, void *closure)
   return 0;
 }
 
+/* Function to get the corresponding breakpoint object for the given
+   bpstats.  */
+
+PyObject *
+gdbpy_breakpoint_from_bpstats (struct bpstats *bs)
+{
+  return (PyObject *) bs->breakpoint_at->py_bp_object;
+}
+
 /* Python function which deletes the underlying GDB breakpoint.  This
    triggers the breakpoint_deleted observer which will call
    gdbpy_breakpoint_deleted; that function cleans up the Python
diff --git a/gdb/python/py-continueevent.c b/gdb/python/py-continueevent.c
new file mode 100644
index 0000000..320c969
--- /dev/null
+++ b/gdb/python/py-continueevent.c
@@ -0,0 +1,65 @@
+/* Python interface to inferior continue events.
+
+   Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "py-event.h"
+
+static PyTypeObject continue_event_object_type;
+
+typedef struct
+{
+  event_object event;
+} continue_event_object;
+
+static void
+continue_evpy_dealloc (PyObject *self)
+{
+  evpy_dealloc (self);
+}
+
+continue_event_object *
+create_continue_event_object (void)
+{
+  return (continue_event_object *)
+      create_event_object (&continue_event_object_type);
+}
+
+/* Callback function which notifies observers when a continue event occurs.
+   This function will create a new Python continue event object.
+   Return -1 if emit fails.  */
+
+int
+emit_continue_event (ptid_t ptid)
+{
+  event_object *event;
+
+  if (evregpy_no_listeners_p (gdb_py_events.cont))
+    return 0;
+
+  event = (event_object *) create_continue_event_object ();
+  if (event)
+    return evpy_emit_event (event, gdb_py_events.cont);
+  return -1;
+}
+
+GDBPY_NEW_EVENT_TYPE (continue,
+                      "gdb.ContinueEvent",
+                      "ContinueEvent",
+                      "GDB continue event object",
+                      event_object_type,
+                      static);
diff --git a/gdb/python/py-event.c b/gdb/python/py-event.c
new file mode 100644
index 0000000..99dd7bc
--- /dev/null
+++ b/gdb/python/py-event.c
@@ -0,0 +1,178 @@
+/* Python interface to inferior events.
+
+   Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "py-event.h"
+
+void
+evpy_dealloc (PyObject *self)
+{
+  Py_XDECREF (((event_object *) self)->dict);
+  self->ob_type->tp_free (self);
+}
+
+event_object *
+create_event_object (PyTypeObject *py_type)
+{
+  event_object *event_obj;
+
+  event_obj = PyObject_New (event_object, py_type);
+  if (!event_obj)
+    goto fail;
+
+  event_obj->dict = PyDict_New ();
+  if (!event_obj->dict)
+    goto fail;
+
+  return event_obj;
+
+ fail:
+  Py_XDECREF (event_obj);
+  return NULL;
+}
+
+/* Add the attribute ATTR to the event object EVENT.  In
+   python this attribute will be accessible by the name NAME.
+   returns 0 if the operation succeeds and -1 otherwise.  */
+
+int
+evpy_add_attribute (event_object *event, char *name, PyObject *attr)
+{
+  return PyObject_SetAttrString ((PyObject *) event, name, attr);
+}
+
+/* Initialize the Python event code.  */
+
+void
+gdbpy_initialize_event (void)
+{
+  gdbpy_initialize_event_generic (&event_object_type,
+                                  "Event");
+}
+
+/* Initialize the given event type.  If BASE is not NULL it will
+  be set as the types base.
+  Returns 0 if initialization was successful -1 otherwise.  */
+
+int
+gdbpy_initialize_event_generic (PyTypeObject *type,
+                                char *name)
+{
+  if (PyType_Ready (type) < 0)
+    goto fail;
+
+  Py_INCREF (type);
+  if (PyModule_AddObject (gdb_module, name, (PyObject *) type) < 0)
+    goto fail;
+
+  return 0;
+
+  fail:
+    Py_XDECREF (type);
+    return -1;
+}
+
+
+/* Notify the list of listens that the given EVENT has occurred.
+   returns 0 if emit is successful -1 otherwise.  */
+
+int
+evpy_emit_event (event_object *event,
+                 eventregistry_object *registry)
+{
+  PyObject *callback_list, *event_obj = (PyObject *) event;
+  PyObject *callback_list_copy = NULL;
+  Py_ssize_t i;
+
+  callback_list = (PyObject *) registry->callbacks;
+
+  /* Create a copy of call back list and use that for
+     notifying listeners to avoid skipping callbacks
+     in the case of a callback being disconnected during
+     a notification.  */
+  callback_list_copy = PySequence_List (callback_list);
+  if (!callback_list_copy)
+    goto fail;
+
+  for (i = 0; i < PyList_Size (callback_list_copy); i++)
+    {
+      PyObject *func = PyList_GetItem (callback_list_copy, i);
+
+      if (func == NULL)
+	goto fail;
+
+      if (!PyObject_CallFunctionObjArgs (func, event_obj, NULL))
+	{
+	  /* Print the trace here, but keep going -- we want to try to
+	     call all of the callbacks even if one is broken.  */
+	  gdbpy_print_stack ();
+	}
+    }
+
+  Py_XDECREF (callback_list_copy);
+  Py_XDECREF (event_obj);
+  return 0;
+
+ fail:
+  gdbpy_print_stack ();
+  Py_XDECREF (callback_list_copy);
+  Py_XDECREF (event_obj);
+  return -1;
+}
+
+PyTypeObject event_object_type =
+{
+  PyObject_HEAD_INIT (NULL)
+  0,                                          /* ob_size */
+  "gdb.Event",                                /* tp_name */
+  sizeof (event_object),                      /* tp_basicsize */
+  0,                                          /* tp_itemsize */
+  evpy_dealloc,                               /* tp_dealloc */
+  0,                                          /* tp_print */
+  0,                                          /* tp_getattr */
+  0,                                          /* tp_setattr */
+  0,                                          /* tp_compare */
+  0,                                          /* tp_repr */
+  0,                                          /* tp_as_number */
+  0,                                          /* tp_as_sequence */
+  0,                                          /* tp_as_mapping */
+  0,                                          /* tp_hash  */
+  0,                                          /* tp_call */
+  0,                                          /* tp_str */
+  0,                                          /* tp_getattro */
+  0,                                          /* tp_setattro */
+  0,                                          /* tp_as_buffer */
+  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,   /* tp_flags */
+  "GDB event object",                         /* tp_doc */
+  0,                                          /* tp_traverse */
+  0,                                          /* tp_clear */
+  0,                                          /* tp_richcompare */
+  0,                                          /* tp_weaklistoffset */
+  0,                                          /* tp_iter */
+  0,                                          /* tp_iternext */
+  0,                                          /* tp_methods */
+  0,                                          /* tp_members */
+  0,                                          /* tp_getset */
+  0,                                          /* tp_base */
+  0,                                          /* tp_dict */
+  0,                                          /* tp_descr_get */
+  0,                                          /* tp_descr_set */
+  offsetof (event_object, dict),              /* tp_dictoffset */
+  0,                                          /* tp_init */
+  0                                           /* tp_alloc */
+};
diff --git a/gdb/python/py-event.h b/gdb/python/py-event.h
new file mode 100644
index 0000000..8d7af2a
--- /dev/null
+++ b/gdb/python/py-event.h
@@ -0,0 +1,119 @@
+/* Python interface to inferior events.
+
+   Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef GDB_PY_EVENT_H
+#define GDB_PY_EVENT_H
+
+#include "defs.h"
+#include "py-events.h"
+#include "command.h"
+#include "python-internal.h"
+#include "inferior.h"
+
+/* This macro creates the following functions:
+
+     gdbpy_initialize_{NAME}_event
+     Used to add the newly created event type to the gdb module.
+
+   and the python type data structure for the event:
+
+     struct PyTypeObject {NAME}_event_object_type
+
+  NAME is the name of the event.
+  PY_PATH is a string representing the module and python name of
+    the event.
+  PY_NAME a string representing what the event should be called in
+    python.
+  DOC Python documentation for the new event type
+  BASE the base event for this event usually just event_object_type.
+  QUAL qualification for the create event usually 'static'
+*/
+
+#define GDBPY_NEW_EVENT_TYPE(name, py_path, py_name, doc, base, qual) \
+\
+    qual PyTypeObject name##_event_object_type = \
+    { \
+      PyObject_HEAD_INIT (NULL) \
+      0,                                          /* ob_size */ \
+      py_path,                                    /* tp_name */ \
+      sizeof (name##_event_object),               /* tp_basicsize */ \
+      0,                                          /* tp_itemsize */ \
+      name##_evpy_dealloc,                        /* tp_dealloc */ \
+      0,                                          /* tp_print */ \
+      0,                                          /* tp_getattr */ \
+      0,                                          /* tp_setattr */ \
+      0,                                          /* tp_compare */ \
+      0,                                          /* tp_repr */ \
+      0,                                          /* tp_as_number */ \
+      0,                                          /* tp_as_sequence */ \
+      0,                                          /* tp_as_mapping */ \
+      0,                                          /* tp_hash  */ \
+      0,                                          /* tp_call */ \
+      0,                                          /* tp_str */ \
+      0,                                          /* tp_getattro */ \
+      0,                                          /* tp_setattro */ \
+      0,                                          /* tp_as_buffer */ \
+      Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,   /* tp_flags */ \
+      doc,                                        /* tp_doc */ \
+      0,                                          /* tp_traverse */ \
+      0,                                          /* tp_clear */ \
+      0,                                          /* tp_richcompare */ \
+      0,                                          /* tp_weaklistoffset */ \
+      0,                                          /* tp_iter */ \
+      0,                                          /* tp_iternext */ \
+      0,                                          /* tp_methods */ \
+      0,                                          /* tp_members */ \
+      0,                                          /* tp_getset */ \
+      &base,                                      /* tp_base */ \
+      0,                                          /* tp_dict */ \
+      0,                                          /* tp_descr_get */ \
+      0,                                          /* tp_descr_set */ \
+      0,                                          /* tp_dictoffset */ \
+      0,                                          /* tp_init */ \
+      0                                           /* tp_alloc */ \
+    }; \
+\
+void \
+gdbpy_initialize_##name##_event (void) \
+{ \
+  gdbpy_initialize_event_generic (&name##_event_object_type, \
+                                  py_name); \
+}
+
+typedef struct
+{
+  PyObject_HEAD
+
+  PyObject *dict;
+} event_object;
+
+extern int emit_stop_event (struct bpstats *bs, enum target_signal stop_signal);
+extern int emit_continue_event (ptid_t ptid);
+extern int emit_exited_event (LONGEST *exit_code);
+
+extern int evpy_emit_event (event_object *event,
+                            eventregistry_object *registry);
+extern event_object * create_event_object (PyTypeObject *py_type);
+extern void evpy_dealloc (PyObject *self);
+extern int evpy_add_attribute (event_object *event,
+                               char *name, PyObject *attr);
+int gdbpy_initialize_event_generic (PyTypeObject *type, char *name);
+
+
+#endif /* GDB_PY_EVENT_H */
diff --git a/gdb/python/py-events.h b/gdb/python/py-events.h
new file mode 100644
index 0000000..31e5604
--- /dev/null
+++ b/gdb/python/py-events.h
@@ -0,0 +1,60 @@
+/* Python interface to inferior events.
+
+   Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef GDB_PY_EVENTS_H
+#define GDB_PY_EVENTS_H
+
+#include "defs.h"
+#include "command.h"
+#include "python-internal.h"
+#include "inferior.h"
+
+
+/* Stores a list of objects to be notified when the event for which this
+   registry tracks occurs.  */
+
+typedef struct
+{
+  PyObject_HEAD
+
+  PyListObject *callbacks;
+} eventregistry_object;
+
+/* Struct holding references to event registries both in python and c.
+   This is meant to be a singleton.  */
+
+typedef struct
+{
+  eventregistry_object *stop;
+  eventregistry_object *breakpoint;
+  eventregistry_object *signal;
+  eventregistry_object *cont;
+  eventregistry_object *exited;
+
+  PyObject *module;
+
+} events_object;
+
+/* Python events singleton.  */
+events_object gdb_py_events;
+
+extern eventregistry_object *create_eventregistry_object (void);
+extern int evregpy_no_listeners_p (eventregistry_object *registry);
+
+#endif /* GDB_PY_EVENTS_H */
diff --git a/gdb/python/py-evtregistry.c b/gdb/python/py-evtregistry.c
new file mode 100644
index 0000000..e85e483
--- /dev/null
+++ b/gdb/python/py-evtregistry.c
@@ -0,0 +1,180 @@
+/* Python interface to inferior thread event registries.
+
+   Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "command.h"
+#include "py-events.h"
+
+static PyTypeObject eventregistry_object_type;
+
+/* Implementation of EventRegistry.connect () -> NULL.
+   Add FUNCTION to the list of listeners.  */
+
+static PyObject *
+evregpy_connect (PyObject *self, PyObject *function)
+{
+  PyObject *func;
+  PyObject *callback_list = (PyObject *)
+    (((eventregistry_object *) self)->callbacks);
+
+  if (!PyArg_ParseTuple (function, "O", &func))
+    return NULL;
+
+  if (!PyCallable_Check (func))
+    {
+      PyErr_SetString (PyExc_RuntimeError, "Function is not callable");
+      return NULL;
+    }
+
+  PyList_Append (callback_list, func);
+
+  Py_RETURN_NONE;
+}
+
+/* Implementation of EventRegistry.disconnect () -> NULL.
+   Remove FUNCTION from the list of listeners.  */
+
+static PyObject *
+evregpy_disconnect (PyObject *self, PyObject *function)
+{
+  PyObject *func;
+  int index;
+  PyObject *callback_list = (PyObject *)
+    (((eventregistry_object *) self)->callbacks);
+
+  if (!PyArg_ParseTuple (function, "O", &func))
+    return NULL;
+
+  if (!PyCallable_Check (func))
+    {
+      PyErr_SetString (PyExc_RuntimeError, "Function is not callable");
+      return NULL;
+    }
+
+  index = PySequence_Index (callback_list, func);
+  if (index < 0)
+    {
+      PyErr_SetString (PyExc_RuntimeError, "Function not found");
+      return NULL;
+    }
+
+  if (PySequence_DelItem (callback_list, index) < 0)
+    return NULL;
+
+  Py_RETURN_NONE;
+}
+
+/* Create a new event registry.  This function uses PyObject_New
+   and therefore returns a new reference that callers must handle.  */
+
+eventregistry_object *
+create_eventregistry_object (void)
+{
+  eventregistry_object *eventregistry_obj;
+
+  eventregistry_obj = PyObject_New (eventregistry_object,
+                                    &eventregistry_object_type);
+
+  if (!eventregistry_obj)
+    return NULL;
+
+  eventregistry_obj->callbacks = (PyListObject *) PyList_New (0);
+  if (!eventregistry_obj->callbacks)
+    return NULL;
+
+  return eventregistry_obj;
+}
+
+static void
+evregpy_dealloc (PyObject *self)
+{
+  Py_XDECREF (((eventregistry_object *) self)->callbacks);
+  self->ob_type->tp_free (self);
+}
+
+/* Initialize the Python event registry code.  */
+
+void
+gdbpy_initialize_eventregistry (void)
+{
+  if (PyType_Ready (&eventregistry_object_type) < 0)
+    return;
+
+  Py_INCREF (&eventregistry_object_type);
+  PyModule_AddObject (gdb_module, "EventRegistry",
+                      (PyObject *) &eventregistry_object_type);
+}
+
+/* Retern the number of listeners currently connected to this
+   registry.  */
+
+int
+evregpy_no_listeners_p (eventregistry_object *registry)
+{
+  return PyList_Size ((PyObject *) registry->callbacks) == 0;
+}
+
+static PyMethodDef eventregistry_object_methods[] =
+{
+  { "connect", evregpy_connect, METH_VARARGS, "Add function" },
+  { "disconnect", evregpy_disconnect, METH_VARARGS, "Remove function" },
+  { NULL } /* Sentinel.  */
+};
+
+static PyTypeObject eventregistry_object_type =
+{
+  PyObject_HEAD_INIT (NULL)
+  0,                                          /* ob_size */
+  "gdb.EventRegistry",                        /* tp_name */
+  sizeof (eventregistry_object),              /* tp_basicsize */
+  0,                                          /* tp_itemsize */
+  evregpy_dealloc,                            /* tp_dealloc */
+  0,                                          /* tp_print */
+  0,                                          /* tp_getattr */
+  0,                                          /* tp_setattr */
+  0,                                          /* tp_compare */
+  0,                                          /* tp_repr */
+  0,                                          /* tp_as_number */
+  0,                                          /* tp_as_sequence */
+  0,                                          /* tp_as_mapping */
+  0,                                          /* tp_hash  */
+  0,                                          /* tp_call */
+  0,                                          /* tp_str */
+  0,                                          /* tp_getattro */
+  0,                                          /* tp_setattro */
+  0,                                          /* tp_as_buffer */
+  Py_TPFLAGS_DEFAULT,                         /* tp_flags */
+  "GDB event registry object",                /* tp_doc */
+  0,                                          /* tp_traverse */
+  0,                                          /* tp_clear */
+  0,                                          /* tp_richcompare */
+  0,                                          /* tp_weaklistoffset */
+  0,                                          /* tp_iter */
+  0,                                          /* tp_iternext */
+  eventregistry_object_methods,               /* tp_methods */
+  0,                                          /* tp_members */
+  0,                                          /* tp_getset */
+  0,                                          /* tp_base */
+  0,                                          /* tp_dict */
+  0,                                          /* tp_descr_get */
+  0,                                          /* tp_descr_set */
+  0,                                          /* tp_dictoffset */
+  0,                                          /* tp_init */
+  0                                           /* tp_alloc */
+};
diff --git a/gdb/python/py-evts.c b/gdb/python/py-evts.c
new file mode 100644
index 0000000..8301b99
--- /dev/null
+++ b/gdb/python/py-evts.c
@@ -0,0 +1,77 @@
+/* Python interface to inferior events.
+
+   Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "py-events.h"
+
+/* Initialize python events.  */
+
+static int
+add_new_registry (eventregistry_object **registryp, char *name)
+{
+  *registryp = create_eventregistry_object ();
+
+  if (*registryp == NULL)
+    goto fail;
+
+  if (PyModule_AddObject (gdb_py_events.module,
+                             name,
+                             (PyObject *)(*registryp)) < 0)
+    goto fail;
+
+  return 0;
+
+  fail:
+   Py_XDECREF (*registryp);
+   return -1;
+}
+
+void
+gdbpy_initialize_py_events ()
+{
+  gdb_py_events.module = Py_InitModule ("events", NULL);
+
+  if (!gdb_py_events.module)
+    goto fail;
+
+  if (add_new_registry (&gdb_py_events.stop, "stop") < 0)
+    goto fail;
+
+  if (add_new_registry (&gdb_py_events.breakpoint, "breakpoint") < 0)
+    goto fail;
+
+  if (add_new_registry (&gdb_py_events.cont, "cont") < 0)
+    goto fail;
+
+  if (add_new_registry (&gdb_py_events.exited, "exited") < 0)
+    goto fail;
+
+  if (add_new_registry (&gdb_py_events.signal, "signal") < 0)
+    goto fail;
+
+  Py_INCREF (gdb_py_events.module);
+  if (PyModule_AddObject (gdb_module,
+                          "events",
+                          (PyObject *) gdb_py_events.module) < 0)
+    goto fail;
+
+  return;
+
+  fail:
+   gdbpy_print_stack ();
+}
diff --git a/gdb/python/py-exitedevent.c b/gdb/python/py-exitedevent.c
new file mode 100644
index 0000000..357508c
--- /dev/null
+++ b/gdb/python/py-exitedevent.c
@@ -0,0 +1,86 @@
+/* Python interface to inferior exit events.
+
+   Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "py-event.h"
+
+static PyTypeObject exited_event_object_type;
+
+typedef struct
+{
+  event_object event;
+  PyObject *exit_code;
+} exited_event_object;
+
+static void
+exited_evpy_dealloc (PyObject *self)
+{
+  Py_XDECREF (((exited_event_object *) self)->exit_code);
+  evpy_dealloc (self);
+}
+
+exited_event_object *
+create_exited_event_object (LONGEST *exit_code)
+{
+  exited_event_object *exited_event;
+
+  exited_event = (exited_event_object *)
+      create_event_object (&exited_event_object_type);
+
+  if (!exited_event)
+    goto fail;
+
+  exited_event->exit_code = PyLong_FromLongLong (*exit_code);
+  if (evpy_add_attribute ((event_object *) exited_event,
+                          "exit_code",
+                          exited_event->exit_code) < 0)
+    goto fail;
+
+  return exited_event;
+
+  fail:
+   Py_XDECREF (exited_event);
+   return NULL;
+}
+
+/* Callback that is used when an exit event occurs.  This function
+   will create a new Python exited event object.  */
+
+int
+emit_exited_event (LONGEST *exit_code)
+{
+  event_object *event;
+
+  if (evregpy_no_listeners_p (gdb_py_events.exited))
+    return 0;
+
+  event = (event_object *) create_exited_event_object (exit_code);
+
+  if (event)
+    return evpy_emit_event (event, gdb_py_events.exited);
+
+  return -1;
+}
+
+
+GDBPY_NEW_EVENT_TYPE (exited,
+                      "gdb.ExitedEvent",
+                      "ExitedEvent",
+                      "GDB exited event object",
+                      event_object_type,
+                      static);
diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c
index 6382dab..240c257 100644
--- a/gdb/python/py-inferior.c
+++ b/gdb/python/py-inferior.c
@@ -26,6 +26,9 @@
 #include "python-internal.h"
 #include "arch-utils.h"
 #include "language.h"
+#include "gdb_signals.h"
+#include "py-event.h"
+#include "py-stopevent.h"
 
 struct threadlist_entry {
   thread_object *thread_obj;
@@ -73,6 +76,57 @@ static PyTypeObject membuf_object_type;
       }								\
   } while (0)
 
+static void
+python_on_normal_stop (struct bpstats *bs, int print_frame)
+{
+  struct cleanup *cleanup;
+  enum target_signal stop_signal;
+
+  if (!find_thread_ptid (inferior_ptid))
+      return;
+
+  stop_signal = inferior_thread ()->suspend.stop_signal;
+
+  cleanup = ensure_python_env (get_current_arch (), current_language);
+
+  if (emit_stop_event (bs, stop_signal) < 0)
+    gdbpy_print_stack ();
+
+  do_cleanups (cleanup);
+}
+
+static void
+python_on_resume (ptid_t ptid)
+{
+  struct cleanup *cleanup;
+
+  cleanup = ensure_python_env (get_current_arch (), current_language);
+
+  if (emit_continue_event (ptid) < 0)
+    gdbpy_print_stack ();
+
+  do_cleanups (cleanup);
+}
+
+static void
+python_inferior_exit (struct inferior *inf)
+{
+  struct cleanup *cleanup;
+  LONGEST exitcode_val;
+  LONGEST *exit_code = NULL;
+
+  cleanup = ensure_python_env (get_current_arch (), current_language);
+
+  if (get_internalvar_integer (lookup_internalvar ("_exitcode"), &exitcode_val))
+    exit_code = &exitcode_val;
+
+  if (exit_code
+      && emit_exited_event (exit_code) < 0)
+    gdbpy_print_stack ();
+
+  do_cleanups (cleanup);
+}
+
 /* Return a borrowed reference to the Python object of type Inferior
    representing INFERIOR.  If the object has already been created,
    return it,  otherwise, create it.  Return NULL on failure.  */
@@ -108,8 +162,8 @@ inferior_to_inferior_object (struct inferior *inferior)
 
 /* Finds the Python Inferior object for the given PID.  Returns a
    borrowed reference, or NULL if PID does not match any inferior
-   obect.
-  */
+   object.  */
+
 PyObject *
 find_inferior_object (int pid)
 {
@@ -590,6 +644,9 @@ gdbpy_initialize_inferior (void)
 
   observer_attach_new_thread (add_thread_object);
   observer_attach_thread_exit (delete_thread_object);
+  observer_attach_normal_stop (python_on_normal_stop);
+  observer_attach_target_resumed (python_on_resume);
+  observer_attach_inferior_exit (python_inferior_exit);
 
   if (PyType_Ready (&membuf_object_type) < 0)
     return;
diff --git a/gdb/python/py-signalevent.c b/gdb/python/py-signalevent.c
new file mode 100644
index 0000000..3bf2fa9
--- /dev/null
+++ b/gdb/python/py-signalevent.c
@@ -0,0 +1,64 @@
+/* Python interface to inferior signal stop events.
+
+   Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "py-stopevent.h"
+
+static PyTypeObject signal_event_object_type;
+
+static void
+signal_evpy_dealloc (PyObject *self)
+{
+  Py_XDECREF (((signal_event_object *) self)->stop_signal);
+  stop_evpy_dealloc (self);
+}
+
+signal_event_object *
+create_signal_event_object (enum target_signal stop_signal,
+                            PyObject *stopped_thread)
+{
+  char *signal_name;
+  signal_event_object *signal_event_obj =
+      (signal_event_object *)
+      create_stop_event_object (&signal_event_object_type,
+                                stopped_thread);
+
+  if (!signal_event_obj)
+    goto fail;
+
+  signal_name = (char *) target_signal_to_name (stop_signal);
+  signal_event_obj->stop_signal = PyString_FromString (signal_name);
+
+  if (evpy_add_attribute ((event_object *) signal_event_obj,
+                          "stop_signal",
+                          signal_event_obj->stop_signal) < 0)
+    goto fail;
+
+  return signal_event_obj;
+
+  fail:
+   Py_XDECREF (signal_event_obj);
+   return NULL;
+}
+
+GDBPY_NEW_EVENT_TYPE (signal,
+                      "gdb.SignalEvent",
+                      "SignalEvent",
+                      "GDB signal event object",
+                      stop_event_object_type,
+                      static);
diff --git a/gdb/python/py-stopevent.c b/gdb/python/py-stopevent.c
new file mode 100644
index 0000000..d5a1ec9
--- /dev/null
+++ b/gdb/python/py-stopevent.c
@@ -0,0 +1,161 @@
+/* Python interface to inferior stop events.
+
+   Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "py-stopevent.h"
+
+void
+stop_evpy_dealloc (PyObject *self)
+{
+  Py_XDECREF (((stop_event_object *) self)->inferior_thread);
+  evpy_dealloc (self);
+}
+
+stop_event_object *
+create_stop_event_object (PyTypeObject *py_type, PyObject *thread)
+{
+  stop_event_object *stop_event_obj =
+      (stop_event_object *) create_event_object (py_type);
+
+  if (!stop_event_obj)
+    goto fail;
+
+  stop_event_obj->inferior_thread = thread;
+
+  if (evpy_add_attribute ((event_object *) stop_event_obj,
+                          "inferior_thread",
+                          stop_event_obj->inferior_thread) < 0)
+    goto fail;
+
+  return stop_event_obj;
+
+  fail:
+   Py_XDECREF (stop_event_obj);
+   return NULL;
+
+}
+
+/* Stop events can either be thread specific or process wide.  If gdb is
+   running in non-stop mode then the event is thread specific, otherwise
+   it is process wide.
+   This function returns the currently stopped thread in non-stop mode and
+   Py_None otherwise.  */
+
+PyObject *
+get_stopped_thread ()
+{
+  PyObject *stopped_thread = NULL;
+
+  if (non_stop)
+    stopped_thread = (PyObject *) find_thread_object (inferior_ptid);
+  else
+    stopped_thread = Py_None;
+
+  if (!stopped_thread)
+    return NULL;
+
+  Py_INCREF (stopped_thread);
+
+  return stopped_thread;
+}
+
+/* Callback observers when a stop event occurs.  This function will create a new
+   Python stop event object.  If only a specific thread is stopped the thread
+   object of the event will be set to that thread.  Otherwise, if all threads
+   are stopped thread object will be set to None.
+   return 0 if the event was created and emitted successfully otherwise
+   returns -1.  */
+
+int
+emit_stop_event (struct bpstats *bs, enum target_signal stop_signal)
+{
+  stop_event_object *stop_event_obj = NULL; /* Appease GCC warning.  */
+  eventregistry_object *registry = NULL;
+  PyObject* stopped_thread = NULL;
+
+  if (bs && bs->breakpoint_at
+      && bs->breakpoint_at->type == bp_breakpoint)
+    {
+      if (evregpy_no_listeners_p (gdb_py_events.breakpoint))
+	return 0;
+
+      stopped_thread = get_stopped_thread();
+      if (!stopped_thread)
+	goto fail;
+
+      stop_event_obj =
+	  (stop_event_object *)
+	  create_breakpoint_event_object (bs, stopped_thread);
+      if (!stop_event_obj)
+	goto fail;
+
+      registry = gdb_py_events.breakpoint;
+    }
+
+  /* Check if the signal is "Signal 0" or "Trace/breakpoint trap".  */
+  if (stop_signal != TARGET_SIGNAL_0
+      && stop_signal != TARGET_SIGNAL_TRAP)
+    {
+      if (evregpy_no_listeners_p (gdb_py_events.signal))
+	return 0;
+
+      stopped_thread = get_stopped_thread();
+      if (!stopped_thread)
+	goto fail;
+
+      stop_event_obj =
+	  (stop_event_object *)
+	  create_signal_event_object (stop_signal, stopped_thread);
+      if (!stop_event_obj)
+	goto fail;
+
+      registry = gdb_py_events.signal;
+    }
+
+  /* If all fails emit an unknown stop event.  All event types should
+     be known and this should eventually be unused.  */
+  if (!stop_event_obj)
+    {
+      if (evregpy_no_listeners_p (gdb_py_events.stop))
+	return 0;
+
+      stopped_thread = get_stopped_thread();
+      if (!stopped_thread)
+	goto fail;
+
+      stop_event_obj = create_stop_event_object (&stop_event_object_type,
+                                                 stopped_thread);
+      if (!stop_event_obj)
+	goto fail;
+
+      registry = gdb_py_events.stop;
+    }
+
+  return evpy_emit_event ((event_object *) stop_event_obj, registry);
+
+  fail:
+   Py_XDECREF(stopped_thread);
+   return -1;
+}
+
+GDBPY_NEW_EVENT_TYPE (stop,
+                      "gdb.StopEvent",
+                      "StopEvent",
+                      "GDB stop event object",
+                      event_object_type,
+                      /*no qual*/);
diff --git a/gdb/python/py-stopevent.h b/gdb/python/py-stopevent.h
new file mode 100644
index 0000000..bf0b526
--- /dev/null
+++ b/gdb/python/py-stopevent.h
@@ -0,0 +1,58 @@
+/* Python interface to inferior events.
+
+   Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef GDB_PY_STOPEVENT_H
+#define GDB_PY_STOPEVENT_H
+
+#include "py-event.h"
+
+typedef struct
+{
+  event_object event;
+  PyObject *inferior_thread;
+} stop_event_object;
+
+typedef struct
+{
+  stop_event_object stop_event;
+  PyObject *breakpoint;
+} breakpoint_event_object;
+
+typedef struct
+{
+  stop_event_object stop_event;
+  PyObject *stop_signal;
+} signal_event_object;
+
+extern stop_event_object * create_stop_event_object (PyTypeObject *py_type,
+                                                     PyObject *thread);
+extern void stop_evpy_dealloc (PyObject *self);
+
+extern int emit_stop_event (struct bpstats *bs,
+                            enum target_signal stop_signal);
+
+extern breakpoint_event_object *
+create_breakpoint_event_object (struct bpstats *bs,
+                                PyObject *stopped_thread);
+
+extern signal_event_object *
+create_signal_event_object (enum target_signal stop_signal,
+                            PyObject *stopped_thread);
+
+#endif /* GDB_PY_STOPEVENT_H */
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 30d7533..4e141d1 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -79,6 +79,7 @@ typedef int Py_ssize_t;
 
 /* Also needed to parse enum var_types. */
 #include "command.h"
+#include "breakpoint.h"
 
 #include "exceptions.h"
 
@@ -86,11 +87,18 @@ struct block;
 struct value;
 struct language_defn;
 struct program_space;
+struct bpstats;
 
 extern PyObject *gdb_module;
 extern PyTypeObject value_object_type;
 extern PyTypeObject block_object_type;
 extern PyTypeObject symbol_object_type;
+extern PyTypeObject event_object_type;
+extern PyTypeObject events_object_type;
+extern PyTypeObject stop_event_object_type;
+
+/* Defined in py-breakpoint.c */
+typedef struct breakpoint_object breakpoint_object;
 
 typedef struct
 {
@@ -141,6 +149,8 @@ PyObject *objfpy_get_printers (PyObject *, void *);
 thread_object *create_thread_object (struct thread_info *tp);
 thread_object *find_thread_object (ptid_t ptid);
 PyObject *find_inferior_object (int pid);
+PyObject *inferior_to_inferior_object (struct inferior *inferior);
+PyObject *gdbpy_breakpoint_from_bpstats (struct bpstats *bs);
 
 struct block *block_object_to_block (PyObject *obj);
 struct symbol *symbol_object_to_symbol (PyObject *obj);
@@ -167,6 +177,14 @@ void gdbpy_initialize_lazy_string (void);
 void gdbpy_initialize_parameters (void);
 void gdbpy_initialize_thread (void);
 void gdbpy_initialize_inferior (void);
+void gdbpy_initialize_eventregistry (void);
+void gdbpy_initialize_event (void);
+void gdbpy_initialize_py_events (void);
+void gdbpy_initialize_stop_event (void);
+void gdbpy_initialize_signal_event (void);
+void gdbpy_initialize_breakpoint_event (void);
+void gdbpy_initialize_continue_event (void);
+void gdbpy_initialize_exited_event (void);
 
 struct cleanup *make_cleanup_py_decref (PyObject *py);
 
diff --git a/gdb/python/python.c b/gdb/python/python.c
index d009be9..04c072a 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -1001,6 +1001,15 @@ Enables or disables printing of Python stack traces."),
   gdbpy_initialize_inferior ();
   gdbpy_initialize_events ();
 
+  gdbpy_initialize_eventregistry ();
+  gdbpy_initialize_py_events ();
+  gdbpy_initialize_event ();
+  gdbpy_initialize_stop_event ();
+  gdbpy_initialize_signal_event ();
+  gdbpy_initialize_breakpoint_event ();
+  gdbpy_initialize_continue_event ();
+  gdbpy_initialize_exited_event ();
+
   PyRun_SimpleString ("import gdb");
   PyRun_SimpleString ("gdb.pretty_printers = []");
 
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 0417538..2e9f64b 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2010-12-23  Sami Wagiaalla  <swagiaal@redhat.com>
+
+	* gdb.python/py-events-threads.c: New file.
+	* gdb.python/py-events-threads.exp: New file.
+	* gdb.python/py-events.py: New file.
+	* gdb.python/py-events.exp: New file.
+	* gdb.python/py-events.c: New file.
+
 2010-12-12  Stan Shebs  <stan@codesourcery.com>
 
 	* gdb.trace/tsv.exp: Test print command on trace state variables.
diff --git a/gdb/testsuite/gdb.python/py-events.c b/gdb/testsuite/gdb.python/py-events.c
new file mode 100644
index 0000000..ceb697e
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-events.c
@@ -0,0 +1,29 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2010, 2011 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see  <http://www.gnu.org/licenses/>.
+*/
+
+int second(){
+  return 12;
+}
+
+int first(){
+  return second();
+}
+
+int main (){
+  return first();
+}
diff --git a/gdb/testsuite/gdb.python/py-events.exp b/gdb/testsuite/gdb.python/py-events.exp
new file mode 100644
index 0000000..e5d6daf
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-events.exp
@@ -0,0 +1,59 @@
+# Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite.  It tests Python-based
+# pretty-printing for the CLI.
+
+# Skip all tests if Python scripting is not enabled.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+load_lib gdb-python.exp
+
+set testfile "py-events"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+set pyfile ${srcdir}/${subdir}/${testfile}.py
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
+    return -1
+}
+
+if { [skip_python_tests] } { continue }
+
+gdb_test_no_output "python execfile ('${pyfile}')" ""
+
+if ![runto_main ] then {
+    fail "Can't run to main"
+    return -1
+}
+
+gdb_test "Test_Events" "Event testers registered."
+
+gdb_breakpoint "first"
+
+# Test continue event and breakpoint stop event
+gdb_test "continue" ".*event type: continue.*
+.*event type: stop.*
+.*stop reason: breakpoint.*
+.*breakpoint number: 2.*
+all threads stopped"
+
+#test exited event.
+gdb_test "continue" ".*event type: continue.*
+.*event type: exit.*
+.*exit code: 12.*"
diff --git a/gdb/testsuite/gdb.python/py-events.py b/gdb/testsuite/gdb.python/py-events.py
new file mode 100644
index 0000000..57d8842
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-events.py
@@ -0,0 +1,62 @@
+# Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite.  It tests python pretty
+# printers.
+import gdb
+
+def signal_stop_handler (event):
+    if (isinstance (event, gdb.StopEvent)):
+        print "event type: stop"
+    if (isinstance (event, gdb.SignalEvent)):
+        print "stop reason: signal"
+        print "stop signal: %s" % (event.stop_signal)
+        if ( event.inferior_thread is not None) :
+            print "thread num: %s" % (event.inferior_thread.num);
+
+def breakpoint_stop_handler (event):
+    if (isinstance (event, gdb.StopEvent)):
+        print "event type: stop"
+    if (isinstance (event, gdb.BreakpointEvent)):
+        print "stop reason: breakpoint"
+        print "breakpoint number: %s" % (event.breakpoint.number)
+        if ( event.inferior_thread is not None) :
+            print "thread num: %s" % (event.inferior_thread.num);
+        else:
+            print "all threads stopped"
+
+def exit_handler (event):
+    if (isinstance (event, gdb.ExitedEvent)):
+        print "event type: exit"
+    print "exit code: %d" % (event.exit_code)
+
+def continue_handler (event):
+    if (isinstance (event, gdb.ContinueEvent)):
+        print "event type: continue"
+
+class test_events (gdb.Command):
+    """Test events."""
+
+    def __init__ (self):
+        gdb.Command.__init__ (self, "test_events", gdb.COMMAND_STACK)
+
+    def invoke (self, arg, from_tty):
+        gdb.events.signal.connect (signal_stop_handler)
+        gdb.events.breakpoint.connect (breakpoint_stop_handler)
+        gdb.events.exited.connect (exit_handler)
+        gdb.events.cont.connect (continue_handler)
+        print "Event testers registered."
+
+test_events ()
diff --git a/gdb/testsuite/gdb.python/py-evthreads.c b/gdb/testsuite/gdb.python/py-evthreads.c
new file mode 100644
index 0000000..28124fa
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-evthreads.c
@@ -0,0 +1,54 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2010, 2011 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see  <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <pthread.h>
+#include <unistd.h>
+
+pthread_t thread2_id;
+pthread_t thread3_id;
+
+void* thread3 (void* d)
+{
+  int count3 = 0;
+  count3++;
+
+  int *bad;
+  *bad = 1;
+
+  return NULL;
+}
+
+void* thread2 (void* d)
+{
+  int count2 = 0;
+  count2++;
+  return NULL;
+}
+
+int main (){
+
+  pthread_create (&thread2_id, NULL, thread2, NULL);
+  pthread_create (&thread3_id, NULL, thread3, NULL);
+
+  int count1 = 0; // stop1
+  count1++;
+
+  pthread_join (thread3_id, NULL);
+  return 12;
+}
diff --git a/gdb/testsuite/gdb.python/py-evthreads.exp b/gdb/testsuite/gdb.python/py-evthreads.exp
new file mode 100644
index 0000000..eb1ecc0
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-evthreads.exp
@@ -0,0 +1,89 @@
+# Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite.  It tests Python-based
+# pretty-printing for the CLI.
+
+# Skip all tests if Python scripting is not enabled.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+load_lib gdb-python.exp
+
+set testfile "py-evthreads"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+set pyfile ${srcdir}/${subdir}/py-events.py
+
+gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug nowarnings}
+clean_restart $testfile
+
+if { [skip_python_tests] } { continue }
+
+gdb_test_no_output "python execfile ('${pyfile}')" ""
+
+gdb_test "Test_Events" "Event testers registered."
+gdb_test_no_output "set non-stop on"
+gdb_test_no_output "set target-async on"
+
+gdb_breakpoint "main"
+gdb_breakpoint "thread2"
+gdb_breakpoint "thread3"
+
+send_gdb "run\n"
+gdb_expect {
+    -re "event type: stop.*
+.*stop reason: breakpoint.*
+.*breakpoint number: 1.*
+.*thread num: 1.*" {
+        pass "reached breakpoint 1"
+    }
+    timeout {
+	    fail "did not reach breakpoint 1"
+	}
+}
+
+send_gdb "next\n"
+gdb_expect {
+    -re "event type: stop.*
+.*stop reason: breakpoint.*
+.*breakpoint number: 2.*
+.*thread num: 2.*" {
+        pass "reached breakpoint 2"
+    }
+    timeout {
+	    fail "did not reach breakpoint 2"
+	}
+}
+
+send_gdb "next\n"
+gdb_expect {
+    -re "event type: stop.*
+.*stop reason: breakpoint.*
+.*breakpoint number: 3.*
+.*thread num: 3.*" {
+        pass "reached breakpoint 3"
+    }
+    timeout {
+	    fail "did not reach breakpoint 3"
+	}
+}
+
+gdb_test "continue -a" ".*event type: stop.*
+.*stop reason: signal.*
+.*stop signal: SIGSEGV.*
+.*thread num: 3.*"

  reply	other threads:[~2011-01-17 21:06 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-01-04 15:54 sami wagiaalla
2011-01-04 18:22 ` Eli Zaretskii
2011-01-04 20:09 ` Tom Tromey
2011-01-17 22:59   ` sami wagiaalla [this message]
2011-01-19 16:42     ` Tom Tromey
2011-01-21 23:06       ` sami wagiaalla
2011-01-28 16:21         ` Tom Tromey
2011-02-02 21:04           ` sami wagiaalla
2011-02-02 21:35             ` Tom Tromey
2011-02-03 16:41               ` sami wagiaalla
2011-02-03 18:26                 ` Eli Zaretskii
2011-02-03 19:45                   ` sami wagiaalla
2011-02-03 21:42                 ` Tom Tromey
2011-02-04 20:07                   ` sami wagiaalla
2011-02-04 20:29                     ` Tom Tromey
2011-02-04 20:35                       ` sami wagiaalla
2011-02-04 23:00                         ` Paul Pluzhnikov
2011-02-05  5:44                           ` Hui Zhu
2011-02-07 15:22                             ` sami wagiaalla
2011-02-07 15:24                               ` Tom Tromey
2011-02-07 15:34                                 ` Paul Pluzhnikov
2011-02-07 16:01                                   ` sami wagiaalla
2011-02-07 15:39                                 ` sami wagiaalla
2011-04-20 20:26                         ` Patch for non-stop remote assertion (was: RE: [patch] Support inferior events in python) Marc Khouzam
2011-04-25 18:12                           ` Patch for non-stop remote assertion Tom Tromey
2011-04-25 18:31                             ` Marc Khouzam
2011-05-16 15:41                               ` Marc Khouzam
2011-05-19 18:38                               ` Tom Tromey
2011-02-09  7:55                     ` [patch] Support inferior events in python Jan Kratochvil
2011-02-09 16:19                       ` sami wagiaalla
2011-02-09 16:30                         ` Jan Kratochvil
2011-02-11 15:28                           ` sami wagiaalla
2011-02-11 15:55                             ` Joel Brobecker
2011-02-11 19:19                               ` sami wagiaalla
2011-02-11 19:46                                 ` Jan Kratochvil
2011-02-11 15:57                             ` Pedro Alves
2011-02-14 17:36                               ` sami wagiaalla
2011-02-16 11:48                                 ` Jan Kratochvil
2011-07-06 19:42                                   ` Jan Kratochvil
2011-07-07 13:51                                     ` sami wagiaalla
2011-07-07 14:03                                       ` Jan Kratochvil
2011-09-13 21:45                                       ` Jan Kratochvil

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4D34AF3F.4090006@redhat.com \
    --to=swagiaal@redhat.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).