PR python/15620, PR python/18620 - breakpoint events in Python
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-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/15620, PR python/18620: * python.texi (Events In Python): Document new breakpoint events. 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.
This commit is contained in:
parent
93daf339a4
commit
dac790e1b9
8 changed files with 143 additions and 0 deletions
|
@ -1,3 +1,17 @@
|
||||||
|
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>
|
2016-07-13 Tom Tromey <tom@tromey.com>
|
||||||
|
|
||||||
PR python/17698:
|
PR python/17698:
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
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>
|
2016-07-13 Tom Tromey <tom@tromey.com>
|
||||||
|
|
||||||
PR python/17698:
|
PR python/17698:
|
||||||
|
|
|
@ -2965,6 +2965,21 @@ A gdb.Frame object representing the frame in which the register was modified.
|
||||||
Denotes which register was modified.
|
Denotes which register was modified.
|
||||||
@end defvar
|
@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
|
@end table
|
||||||
|
|
||||||
@node Threads In Python
|
@node Threads In Python
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "arch-utils.h"
|
#include "arch-utils.h"
|
||||||
#include "language.h"
|
#include "language.h"
|
||||||
#include "location.h"
|
#include "location.h"
|
||||||
|
#include "py-event.h"
|
||||||
|
|
||||||
/* Number of live breakpoints. */
|
/* Number of live breakpoints. */
|
||||||
static int bppy_live;
|
static int bppy_live;
|
||||||
|
@ -916,6 +917,14 @@ gdbpy_breakpoint_created (struct breakpoint *bp)
|
||||||
gdbpy_print_stack ();
|
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);
|
PyGILState_Release (state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -936,6 +945,15 @@ gdbpy_breakpoint_deleted (struct breakpoint *b)
|
||||||
bp_obj = bp->py_bp_object;
|
bp_obj = bp->py_bp_object;
|
||||||
if (bp_obj)
|
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;
|
bp_obj->bp = NULL;
|
||||||
--bppy_live;
|
--bppy_live;
|
||||||
Py_DECREF (bp_obj);
|
Py_DECREF (bp_obj);
|
||||||
|
@ -944,6 +962,35 @@ gdbpy_breakpoint_deleted (struct breakpoint *b)
|
||||||
PyGILState_Release (state);
|
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. */
|
/* Initialize the Python breakpoint code. */
|
||||||
|
@ -962,6 +1009,7 @@ gdbpy_initialize_breakpoints (void)
|
||||||
|
|
||||||
observer_attach_breakpoint_created (gdbpy_breakpoint_created);
|
observer_attach_breakpoint_created (gdbpy_breakpoint_created);
|
||||||
observer_attach_breakpoint_deleted (gdbpy_breakpoint_deleted);
|
observer_attach_breakpoint_deleted (gdbpy_breakpoint_deleted);
|
||||||
|
observer_attach_breakpoint_modified (gdbpy_breakpoint_modified);
|
||||||
|
|
||||||
/* Add breakpoint types constants. */
|
/* Add breakpoint types constants. */
|
||||||
for (i = 0; pybp_codes[i].name; ++i)
|
for (i = 0; pybp_codes[i].name; ++i)
|
||||||
|
|
|
@ -50,6 +50,9 @@ typedef struct
|
||||||
eventregistry_object *inferior_call;
|
eventregistry_object *inferior_call;
|
||||||
eventregistry_object *memory_changed;
|
eventregistry_object *memory_changed;
|
||||||
eventregistry_object *register_changed;
|
eventregistry_object *register_changed;
|
||||||
|
eventregistry_object *breakpoint_created;
|
||||||
|
eventregistry_object *breakpoint_deleted;
|
||||||
|
eventregistry_object *breakpoint_modified;
|
||||||
|
|
||||||
PyObject *module;
|
PyObject *module;
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,17 @@ gdbpy_initialize_py_events (void)
|
||||||
if (add_new_registry (&gdb_py_events.clear_objfiles, "clear_objfiles") < 0)
|
if (add_new_registry (&gdb_py_events.clear_objfiles, "clear_objfiles") < 0)
|
||||||
return -1;
|
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,
|
if (gdb_pymodule_addobject (gdb_module,
|
||||||
"events",
|
"events",
|
||||||
(PyObject *) gdb_py_events.module) < 0)
|
(PyObject *) gdb_py_events.module) < 0)
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
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>
|
2016-07-13 Tom Tromey <tom@tromey.com>
|
||||||
|
|
||||||
PR python/17698:
|
PR python/17698:
|
||||||
|
|
|
@ -507,6 +507,46 @@ proc test_bkpt_pending {} {
|
||||||
"Check pending status of pending breakpoint"
|
"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_basic
|
||||||
test_bkpt_deletion
|
test_bkpt_deletion
|
||||||
test_bkpt_cond_and_cmds
|
test_bkpt_cond_and_cmds
|
||||||
|
@ -517,3 +557,4 @@ test_bkpt_eval_funcs
|
||||||
test_bkpt_temporary
|
test_bkpt_temporary
|
||||||
test_bkpt_address
|
test_bkpt_address
|
||||||
test_bkpt_pending
|
test_bkpt_pending
|
||||||
|
test_bkpt_events
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue