This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[RFA] PR python/15620, PR python/18620 - breakpoint events in Python
- From: Tom Tromey <tom at tromey dot com>
- To: gdb-patches at sourceware dot org
- Cc: Tom Tromey <tom at tromey dot com>
- Date: Fri, 20 May 2016 14:45:31 -0600
- Subject: [RFA] PR python/15620, PR python/18620 - breakpoint events in Python
- Authentication-results: sourceware.org; auth=none
This patch adds some breakpoint events to Python. In particular,
there is a creation event that is emitted when a breakpoint is
created; a modification event that is emitted when a breakpoint
changes somehow; and a deletion event that is emitted when a
breakpoint is deleted.
In this patch, the event's payload is the breakpoint itself. I
considered making a new event type to hold the breakpoint, but I
didn't see a need. Still, I thought I would mention this as a spot
where some other choice is possible.
Built and regtested on x86-64 Fedora 23.
2016-05-19 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-05-20 Tom Tromey <tom@tromey.com>
PR python/15620, PR python/18620:
* python.texi (Events In Python): Document new breakpoint events.
2016-05-20 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.
---
gdb/ChangeLog | 14 +++++++++
gdb/doc/ChangeLog | 5 ++++
gdb/doc/python.texi | 15 ++++++++++
gdb/python/py-breakpoint.c | 48 ++++++++++++++++++++++++++++++
gdb/python/py-events.h | 3 ++
gdb/python/py-evts.c | 11 +++++++
gdb/testsuite/ChangeLog | 6 ++++
gdb/testsuite/gdb.python/py-breakpoint.exp | 41 +++++++++++++++++++++++++
8 files changed, 143 insertions(+)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 0968b85..1e0afe6 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,17 @@
+2016-05-19 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-05-19 Andreas Schwab <schwab@suse.de>
* ia64-libunwind-tdep.c (libunwind_descr): Add cast from void *.
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index fe2e3be..0d564bf 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,8 @@
+2016-05-20 Tom Tromey <tom@tromey.com>
+
+ PR python/15620, PR python/18620:
+ * python.texi (Events In Python): Document new breakpoint events.
+
2016-05-17 Tom Tromey <tom@tromey.com>
* gdb.texinfo (Supported Languages): Mention Rust. Update menu.
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index ffbf89a..5e3a42c 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -2962,6 +2962,21 @@ A gdb.Frame object representing the frame in which the register was modified.
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 is 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
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index 611a41e..0dce909 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -31,6 +31,7 @@
#include "arch-utils.h"
#include "language.h"
#include "location.h"
+#include "py-event.h"
/* Number of live breakpoints. */
static int bppy_live;
@@ -897,6 +898,14 @@ gdbpy_breakpoint_created (struct breakpoint *bp)
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);
}
@@ -917,6 +926,15 @@ gdbpy_breakpoint_deleted (struct breakpoint *b)
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);
@@ -925,6 +943,35 @@ gdbpy_breakpoint_deleted (struct breakpoint *b)
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);
+}
+
/* Initialize the Python breakpoint code. */
@@ -943,6 +990,7 @@ gdbpy_initialize_breakpoints (void)
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)
diff --git a/gdb/python/py-events.h b/gdb/python/py-events.h
index 9ecee4c..1d74558 100644
--- a/gdb/python/py-events.h
+++ b/gdb/python/py-events.h
@@ -50,6 +50,9 @@ typedef struct
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;
diff --git a/gdb/python/py-evts.c b/gdb/python/py-evts.c
index 95827e4..961c247 100644
--- a/gdb/python/py-evts.c
+++ b/gdb/python/py-evts.c
@@ -89,6 +89,17 @@ gdbpy_initialize_py_events (void)
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)
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index a773c63..b518e64 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2016-05-20 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-05-18 Simon Marchi <simon.marchi@ericsson.com>
* gdb.mi/mi-threads-interrupt.c: New file.
diff --git a/gdb/testsuite/gdb.python/py-breakpoint.exp b/gdb/testsuite/gdb.python/py-breakpoint.exp
index d1d1b22..e926c76 100644
--- a/gdb/testsuite/gdb.python/py-breakpoint.exp
+++ b/gdb/testsuite/gdb.python/py-breakpoint.exp
@@ -494,6 +494,46 @@ proc test_bkpt_address {} {
".*Breakpoint ($decimal)+ at .*$srcfile, line ($decimal)+\."
}
+# 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
@@ -503,3 +543,4 @@ test_bkpt_internal
test_bkpt_eval_funcs
test_bkpt_temporary
test_bkpt_address
+test_bkpt_events
--
2.5.5