+2016-07-13 Tom Tromey <tom@tromey.com>
+
+ PR python/15620, PR python/18620:
+ * python/py-evts.c (gdbpy_initialize_py_events): Call
+ add_new_registry for new events.
+ * python/py-events.h (events_object) <breakpoint_created,
+ breakpoint_deleted, breakpoint_modified>: New fields.
+ * python/py-breakpoint.c (gdbpy_breakpoint_created): Emit the
+ breakpoint changed event.
+ (gdbpy_breakpoint_deleted): Emit the breakpoint deleted event.
+ (gdbpy_breakpoint_modified): New function.
+ (gdbpy_initialize_breakpoints): Attach to the breakpoint modified
+ observer.
+
2016-07-13 Tom Tromey <tom@tromey.com>
PR python/17698:
+2016-07-13 Tom Tromey <tom@tromey.com>
+
+ PR python/15620, PR python/18620:
+ * python.texi (Events In Python): Document new breakpoint events.
+
2016-07-13 Tom Tromey <tom@tromey.com>
PR python/17698:
Denotes which register was modified.
@end defvar
+@item events.breakpoint_created
+This is emitted when a new breakpoint has been created. The argument
+that is passed is the new @code{gdb.Breakpoint} object.
+
+@item events.breakpoint_modified
+This is emitted when a breakpoint has been modified in some way. The
+argument that is passed is the new @code{gdb.Breakpoint} object.
+
+@item events.breakpoint_deleted
+This is emitted when a breakpoint has been deleted. The argument that
+is passed is the @code{gdb.Breakpoint} object. When this event is
+emitted, the @code{gdb.Breakpoint} object will already be in its
+invalid state; that is, the @code{is_valid} method will return
+@code{False}.
+
@end table
@node Threads In Python
#include "arch-utils.h"
#include "language.h"
#include "location.h"
+#include "py-event.h"
/* Number of live breakpoints. */
static int bppy_live;
gdbpy_print_stack ();
}
+ if (!evregpy_no_listeners_p (gdb_py_events.breakpoint_created))
+ {
+ Py_INCREF (newbp);
+ if (evpy_emit_event ((PyObject *) newbp,
+ gdb_py_events.breakpoint_created) < 0)
+ gdbpy_print_stack ();
+ }
+
PyGILState_Release (state);
}
bp_obj = bp->py_bp_object;
if (bp_obj)
{
+ if (!evregpy_no_listeners_p (gdb_py_events.breakpoint_deleted))
+ {
+ PyObject *bp_obj_alias = (PyObject *) bp_obj;
+ Py_INCREF (bp_obj_alias);
+ if (evpy_emit_event (bp_obj_alias,
+ gdb_py_events.breakpoint_deleted) < 0)
+ gdbpy_print_stack ();
+ }
+
bp_obj->bp = NULL;
--bppy_live;
Py_DECREF (bp_obj);
PyGILState_Release (state);
}
+/* Callback that is used when a breakpoint is modified. */
+
+static void
+gdbpy_breakpoint_modified (struct breakpoint *b)
+{
+ int num = b->number;
+ PyGILState_STATE state;
+ struct breakpoint *bp = NULL;
+ gdbpy_breakpoint_object *bp_obj;
+
+ state = PyGILState_Ensure ();
+ bp = get_breakpoint (num);
+ if (bp)
+ {
+ PyObject *bp_obj = (PyObject *) bp->py_bp_object;
+ if (bp_obj)
+ {
+ if (!evregpy_no_listeners_p (gdb_py_events.breakpoint_modified))
+ {
+ Py_INCREF (bp_obj);
+ if (evpy_emit_event (bp_obj,
+ gdb_py_events.breakpoint_modified) < 0)
+ gdbpy_print_stack ();
+ }
+ }
+ }
+ PyGILState_Release (state);
+}
+
\f
/* Initialize the Python breakpoint code. */
observer_attach_breakpoint_created (gdbpy_breakpoint_created);
observer_attach_breakpoint_deleted (gdbpy_breakpoint_deleted);
+ observer_attach_breakpoint_modified (gdbpy_breakpoint_modified);
/* Add breakpoint types constants. */
for (i = 0; pybp_codes[i].name; ++i)
eventregistry_object *inferior_call;
eventregistry_object *memory_changed;
eventregistry_object *register_changed;
+ eventregistry_object *breakpoint_created;
+ eventregistry_object *breakpoint_deleted;
+ eventregistry_object *breakpoint_modified;
PyObject *module;
if (add_new_registry (&gdb_py_events.clear_objfiles, "clear_objfiles") < 0)
return -1;
+ if (add_new_registry (&gdb_py_events.breakpoint_created,
+ "breakpoint_created") < 0)
+ return -1;
+
+ if (add_new_registry (&gdb_py_events.breakpoint_deleted,
+ "breakpoint_deleted") < 0)
+ return -1;
+ if (add_new_registry (&gdb_py_events.breakpoint_modified,
+ "breakpoint_modified") < 0)
+ return -1;
+
if (gdb_pymodule_addobject (gdb_module,
"events",
(PyObject *) gdb_py_events.module) < 0)
+2016-07-13 Tom Tromey <tom@tromey.com>
+
+ PR python/15620, PR python/18620:
+ * gdb.python/py-breakpoint.exp (connect_event, check_last_event)
+ (test_bkpt_events): New procs.
+
2016-07-13 Tom Tromey <tom@tromey.com>
PR python/17698:
"Check pending status of pending breakpoint"
}
+# Helper proc to install an event listener for a given breakpoint
+# event. NAME is the name of the event to listen for.
+proc connect_event {name} {
+ set lambda "lambda x: note_event(\"$name\")"
+ gdb_test_no_output "python gdb.events.$name.connect($lambda)" \
+ "install $name event listener"
+}
+
+# Helper proc to check that the most recently emitted breakpoint event
+# is EXPECTED.
+proc check_last_event {expected} {
+ gdb_test "python print (last_bp_event)" $expected \
+ "check for $expected event"
+}
+
+proc test_bkpt_events {} {
+ global testfile
+
+ clean_restart ${testfile}
+
+ gdb_py_test_multiple "Create event handler" \
+ "python" "" \
+ "def note_event(arg):" "" \
+ " global last_bp_event" "" \
+ " last_bp_event = arg" "" \
+ "end" ""
+ gdb_test_no_output "python last_bp_event = None"
+
+ connect_event breakpoint_created
+ connect_event breakpoint_modified
+ connect_event breakpoint_deleted
+
+ gdb_breakpoint [gdb_get_line_number "Break at add."]
+ check_last_event breakpoint_created
+ gdb_test_no_output "disable 1"
+ check_last_event breakpoint_modified
+ gdb_test_no_output "delete 1"
+ check_last_event breakpoint_deleted
+}
+
test_bkpt_basic
test_bkpt_deletion
test_bkpt_cond_and_cmds
test_bkpt_temporary
test_bkpt_address
test_bkpt_pending
+test_bkpt_events