GNU Binutils with patches for OS216
Revisión | 7c96f8c1dae023c7d0b1cabc5e50c4d18fd06960 (tree) |
---|---|
Tiempo | 2017-09-12 05:15:20 |
Autor | Tom Tromey <tom@trom...> |
Commiter | Tom Tromey |
Add new_inferior, inferior_deleted, and new_thread events
This adds a few new events to gdb's Python layer: new_inferior,
inferior_deleted, and new_thread. I wanted to be able to add a
combined inferior/thread display window to my GUI, and I needed a few
events to make this work. This is PR python/15622.
ChangeLog
2017-09-11 Tom Tromey <tom@tromey.com>
PR python/15622:
* NEWS: Add entry.
* python/python.c (do_start_initialization): Initialize new event
types.
* python/python-internal.h (gdbpy_initialize_new_inferior_event)
(gdbpy_initialize_inferior_deleted_event)
(gdbpy_initialize_new_thread_event): Declare.
* python/py-threadevent.c (create_thread_event_object): Add option
"thread" parameter.
* python/py-inferior.c (new_thread_event_object_type)
(new_inferior_event_object_type)
(inferior_deleted_event_object_type): Declare.
(python_new_inferior, python_inferior_deleted): New functions.
(add_thread_object): Emit new_thread event.
(gdbpy_initialize_inferior): Attach new functions to corresponding
observers.
(new_thread, new_inferior, inferior_deleted): Define new event
types.
* python/py-evts.c (gdbpy_initialize_py_events): Add new
registries.
* python/py-events.h (events_object) <new_inferior,
inferior_deleted, new_thread>: New fields.
* python/py-event.h (create_thread_event_breakpoint): Add optional
"thread" parameter.
doc/ChangeLog
2017-09-11 Tom Tromey <tom@tromey.com>
* python.texi (Events In Python): Document new events.
testsuite/ChangeLog
2017-09-11 Tom Tromey <tom@tromey.com>
* gdb.python/py-infthread.exp: Add tests for new_thread event.
* gdb.python/py-inferior.exp: Add tests for new inferior events.
@@ -1,3 +1,30 @@ | ||
1 | +2017-09-11 Tom Tromey <tom@tromey.com> | |
2 | + | |
3 | + PR python/15622: | |
4 | + * NEWS: Add entry. | |
5 | + * python/python.c (do_start_initialization): Initialize new event | |
6 | + types. | |
7 | + * python/python-internal.h (gdbpy_initialize_new_inferior_event) | |
8 | + (gdbpy_initialize_inferior_deleted_event) | |
9 | + (gdbpy_initialize_new_thread_event): Declare. | |
10 | + * python/py-threadevent.c (create_thread_event_object): Add option | |
11 | + "thread" parameter. | |
12 | + * python/py-inferior.c (new_thread_event_object_type) | |
13 | + (new_inferior_event_object_type) | |
14 | + (inferior_deleted_event_object_type): Declare. | |
15 | + (python_new_inferior, python_inferior_deleted): New functions. | |
16 | + (add_thread_object): Emit new_thread event. | |
17 | + (gdbpy_initialize_inferior): Attach new functions to corresponding | |
18 | + observers. | |
19 | + (new_thread, new_inferior, inferior_deleted): Define new event | |
20 | + types. | |
21 | + * python/py-evts.c (gdbpy_initialize_py_events): Add new | |
22 | + registries. | |
23 | + * python/py-events.h (events_object) <new_inferior, | |
24 | + inferior_deleted, new_thread>: New fields. | |
25 | + * python/py-event.h (create_thread_event_breakpoint): Add optional | |
26 | + "thread" parameter. | |
27 | + | |
1 | 28 | 2017-09-10 Andrew Burgess <andrew.burgess@embecosm.com> |
2 | 29 | |
3 | 30 | * utils.c (abort_with_message): Don't compare gdb_stderr to NULL, |
@@ -15,6 +15,12 @@ | ||
15 | 15 | the remote inferior is started by the GDBserver, use the "unset |
16 | 16 | environment" command. |
17 | 17 | |
18 | +* Python Scripting | |
19 | + | |
20 | + ** New events gdb.new_inferior, gdb.inferior_deleted, and | |
21 | + gdb.new_thread are emitted. See the manual for further | |
22 | + description of these. | |
23 | + | |
18 | 24 | * New features in the GDB remote stub, GDBserver |
19 | 25 | |
20 | 26 | ** New "--selftest" command line option runs some GDBserver self |
@@ -1,3 +1,7 @@ | ||
1 | +2017-09-11 Tom Tromey <tom@tromey.com> | |
2 | + | |
3 | + * python.texi (Events In Python): Document new events. | |
4 | + | |
1 | 5 | 2017-09-04 Pedro Alves <palves@redhat.com> |
2 | 6 | |
3 | 7 | * gdb.texinfo (Variables) <Program Variables>: Document inspecting |
@@ -2989,6 +2989,39 @@ invalid state; that is, the @code{is_valid} method will return | ||
2989 | 2989 | This event carries no payload. It is emitted each time @value{GDBN} |
2990 | 2990 | presents a prompt to the user. |
2991 | 2991 | |
2992 | +@item events.new_inferior | |
2993 | +This is emitted when a new inferior is created. Note that the | |
2994 | +inferior is not necessarily running; in fact, it may not even have an | |
2995 | +associated executable. | |
2996 | + | |
2997 | +The event is of type @code{gdb.NewInferiorEvent}. This has a single | |
2998 | +attribute: | |
2999 | + | |
3000 | +@defvar NewInferiorEvent.inferior | |
3001 | +The new inferior, a @code{gdb.Inferior} object. | |
3002 | +@end defvar | |
3003 | + | |
3004 | +@item events.inferior_deleted | |
3005 | +This is emitted when an inferior has been deleted. Note that this is | |
3006 | +not the same as process exit; it is notified when the inferior itself | |
3007 | +is removed, say via @code{remove-inferiors}. | |
3008 | + | |
3009 | +The event is of type @code{gdb.InferiorDeletedEvent}. This has a single | |
3010 | +attribute: | |
3011 | + | |
3012 | +@defvar NewInferiorEvent.inferior | |
3013 | +The inferior that is being removed, a @code{gdb.Inferior} object. | |
3014 | +@end defvar | |
3015 | + | |
3016 | +@item events.new_thread | |
3017 | +This is emitted when @value{GDBN} notices a new thread. The event is of | |
3018 | +type @code{gdb.NewThreadEvent}, which extends @code{gdb.ThreadEvent}. | |
3019 | +This has a single attribute: | |
3020 | + | |
3021 | +@defvar NewThreadEvent.inferior_thread | |
3022 | +The new thread. | |
3023 | +@end defvar | |
3024 | + | |
2992 | 3025 | @end table |
2993 | 3026 | |
2994 | 3027 | @node Threads In Python |
@@ -125,7 +125,8 @@ extern int evpy_emit_event (PyObject *event, | ||
125 | 125 | eventregistry_object *registry); |
126 | 126 | |
127 | 127 | extern PyObject *create_event_object (PyTypeObject *py_type); |
128 | -extern PyObject *create_thread_event_object (PyTypeObject *py_type); | |
128 | +extern PyObject *create_thread_event_object (PyTypeObject *py_type, | |
129 | + PyObject *thread = nullptr); | |
129 | 130 | extern int emit_new_objfile_event (struct objfile *objfile); |
130 | 131 | extern int emit_clear_objfiles_event (void); |
131 | 132 |
@@ -47,6 +47,9 @@ typedef struct | ||
47 | 47 | eventregistry_object *exited; |
48 | 48 | eventregistry_object *new_objfile; |
49 | 49 | eventregistry_object *clear_objfiles; |
50 | + eventregistry_object *new_inferior; | |
51 | + eventregistry_object *inferior_deleted; | |
52 | + eventregistry_object *new_thread; | |
50 | 53 | eventregistry_object *inferior_call; |
51 | 54 | eventregistry_object *memory_changed; |
52 | 55 | eventregistry_object *register_changed; |
@@ -89,6 +89,15 @@ gdbpy_initialize_py_events (void) | ||
89 | 89 | if (add_new_registry (&gdb_py_events.clear_objfiles, "clear_objfiles") < 0) |
90 | 90 | return -1; |
91 | 91 | |
92 | + if (add_new_registry (&gdb_py_events.new_inferior, "new_inferior") < 0) | |
93 | + return -1; | |
94 | + | |
95 | + if (add_new_registry (&gdb_py_events.inferior_deleted, "inferior_deleted") < 0) | |
96 | + return -1; | |
97 | + | |
98 | + if (add_new_registry (&gdb_py_events.new_thread, "new_thread") < 0) | |
99 | + return -1; | |
100 | + | |
92 | 101 | if (add_new_registry (&gdb_py_events.breakpoint_created, |
93 | 102 | "breakpoint_created") < 0) |
94 | 103 | return -1; |
@@ -30,6 +30,13 @@ | ||
30 | 30 | #include "py-event.h" |
31 | 31 | #include "py-stopevent.h" |
32 | 32 | |
33 | +extern PyTypeObject new_thread_event_object_type | |
34 | + CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object"); | |
35 | +extern PyTypeObject new_inferior_event_object_type | |
36 | + CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object"); | |
37 | +extern PyTypeObject inferior_deleted_event_object_type | |
38 | + CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object"); | |
39 | + | |
33 | 40 | struct threadlist_entry { |
34 | 41 | thread_object *thread_obj; |
35 | 42 | struct threadlist_entry *next; |
@@ -235,6 +242,60 @@ inferior_to_inferior_object (struct inferior *inferior) | ||
235 | 242 | return (PyObject *) inf_obj; |
236 | 243 | } |
237 | 244 | |
245 | +/* Called when a new inferior is created. Notifies any Python event | |
246 | + listeners. */ | |
247 | +static void | |
248 | +python_new_inferior (struct inferior *inf) | |
249 | +{ | |
250 | + if (!gdb_python_initialized) | |
251 | + return; | |
252 | + | |
253 | + gdbpy_enter enter_py (python_gdbarch, python_language); | |
254 | + | |
255 | + if (evregpy_no_listeners_p (gdb_py_events.new_inferior)) | |
256 | + return; | |
257 | + | |
258 | + gdbpy_ref<> inf_obj (inferior_to_inferior_object (inf)); | |
259 | + if (inf_obj == NULL) | |
260 | + { | |
261 | + gdbpy_print_stack (); | |
262 | + return; | |
263 | + } | |
264 | + | |
265 | + gdbpy_ref<> event (create_event_object (&new_inferior_event_object_type)); | |
266 | + if (event == NULL | |
267 | + || evpy_add_attribute (event.get (), "inferior", inf_obj.get ()) < 0 | |
268 | + || evpy_emit_event (event.get (), gdb_py_events.new_inferior) < 0) | |
269 | + gdbpy_print_stack (); | |
270 | +} | |
271 | + | |
272 | +/* Called when an inferior is removed. Notifies any Python event | |
273 | + listeners. */ | |
274 | +static void | |
275 | +python_inferior_deleted (struct inferior *inf) | |
276 | +{ | |
277 | + if (!gdb_python_initialized) | |
278 | + return; | |
279 | + | |
280 | + gdbpy_enter enter_py (python_gdbarch, python_language); | |
281 | + | |
282 | + if (evregpy_no_listeners_p (gdb_py_events.inferior_deleted)) | |
283 | + return; | |
284 | + | |
285 | + gdbpy_ref<> inf_obj (inferior_to_inferior_object (inf)); | |
286 | + if (inf_obj == NULL) | |
287 | + { | |
288 | + gdbpy_print_stack (); | |
289 | + return; | |
290 | + } | |
291 | + | |
292 | + gdbpy_ref<> event (create_event_object (&inferior_deleted_event_object_type)); | |
293 | + if (event == NULL | |
294 | + || evpy_add_attribute (event.get (), "inferior", inf_obj.get ()) < 0 | |
295 | + || evpy_emit_event (event.get (), gdb_py_events.inferior_deleted) < 0) | |
296 | + gdbpy_print_stack (); | |
297 | +} | |
298 | + | |
238 | 299 | /* Finds the Python Inferior object for the given PID. Returns a |
239 | 300 | reference, or NULL if PID does not match any inferior object. */ |
240 | 301 |
@@ -298,6 +359,15 @@ add_thread_object (struct thread_info *tp) | ||
298 | 359 | |
299 | 360 | inf_obj->threads = entry; |
300 | 361 | inf_obj->nthreads++; |
362 | + | |
363 | + if (evregpy_no_listeners_p (gdb_py_events.new_thread)) | |
364 | + return; | |
365 | + | |
366 | + gdbpy_ref<> event (create_thread_event_object (&new_thread_event_object_type, | |
367 | + (PyObject *) thread_obj)); | |
368 | + if (event == NULL | |
369 | + || evpy_emit_event (event.get (), gdb_py_events.new_thread) < 0) | |
370 | + gdbpy_print_stack (); | |
301 | 371 | } |
302 | 372 | |
303 | 373 | static void |
@@ -823,6 +893,8 @@ gdbpy_initialize_inferior (void) | ||
823 | 893 | observer_attach_register_changed (python_on_register_change); |
824 | 894 | observer_attach_inferior_exit (python_inferior_exit); |
825 | 895 | observer_attach_new_objfile (python_new_objfile); |
896 | + observer_attach_inferior_added (python_new_inferior); | |
897 | + observer_attach_inferior_removed (python_inferior_deleted); | |
826 | 898 | |
827 | 899 | membuf_object_type.tp_new = PyType_GenericNew; |
828 | 900 | if (PyType_Ready (&membuf_object_type) < 0) |
@@ -970,3 +1042,19 @@ PyTypeObject membuf_object_type = { | ||
970 | 1042 | 0, /* tp_init */ |
971 | 1043 | 0, /* tp_alloc */ |
972 | 1044 | }; |
1045 | + | |
1046 | +GDBPY_NEW_EVENT_TYPE (new_thread, | |
1047 | + "gdb.NewThreadEvent", | |
1048 | + "NewThreadEvent", | |
1049 | + "GDB new thread event object", | |
1050 | + thread_event_object_type); | |
1051 | +GDBPY_NEW_EVENT_TYPE (new_inferior, | |
1052 | + "gdb.NewInferiorEvent", | |
1053 | + "NewInferiorEvent", | |
1054 | + "GDB new inferior event object", | |
1055 | + event_object_type); | |
1056 | +GDBPY_NEW_EVENT_TYPE (inferior_deleted, | |
1057 | + "gdb.InferiorDeletedEvent", | |
1058 | + "InferiorDeletedEvent", | |
1059 | + "GDB inferior deleted event object", | |
1060 | + event_object_type); |
@@ -48,17 +48,18 @@ get_event_thread (void) | ||
48 | 48 | } |
49 | 49 | |
50 | 50 | PyObject * |
51 | -create_thread_event_object (PyTypeObject *py_type) | |
51 | +create_thread_event_object (PyTypeObject *py_type, PyObject *thread) | |
52 | 52 | { |
53 | - PyObject *thread = NULL; | |
54 | - | |
55 | 53 | gdbpy_ref<> thread_event_obj (create_event_object (py_type)); |
56 | 54 | if (thread_event_obj == NULL) |
57 | 55 | return NULL; |
58 | 56 | |
59 | - thread = get_event_thread (); | |
60 | - if (!thread) | |
61 | - return NULL; | |
57 | + if (thread == NULL) | |
58 | + { | |
59 | + thread = get_event_thread (); | |
60 | + if (!thread) | |
61 | + return NULL; | |
62 | + } | |
62 | 63 | |
63 | 64 | if (evpy_add_attribute (thread_event_obj.get (), |
64 | 65 | "inferior_thread", |
@@ -630,6 +630,12 @@ int gdbpy_initialize_new_objfile_event (void) | ||
630 | 630 | CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; |
631 | 631 | int gdbpy_initialize_clear_objfiles_event (void) |
632 | 632 | CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; |
633 | +int gdbpy_initialize_new_inferior_event (void) | |
634 | + CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; | |
635 | +int gdbpy_initialize_inferior_deleted_event (void) | |
636 | + CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; | |
637 | +int gdbpy_initialize_new_thread_event (void) | |
638 | + CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; | |
633 | 639 | int gdbpy_initialize_arch (void) |
634 | 640 | CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; |
635 | 641 | int gdbpy_initialize_xmethods (void) |
@@ -1603,6 +1603,9 @@ do_start_initialization () | ||
1603 | 1603 | || gdbpy_initialize_thread_event () < 0 |
1604 | 1604 | || gdbpy_initialize_new_objfile_event () < 0 |
1605 | 1605 | || gdbpy_initialize_clear_objfiles_event () < 0 |
1606 | + || gdbpy_initialize_new_inferior_event () < 0 | |
1607 | + || gdbpy_initialize_inferior_deleted_event () < 0 | |
1608 | + || gdbpy_initialize_new_thread_event () < 0 | |
1606 | 1609 | || gdbpy_initialize_arch () < 0 |
1607 | 1610 | || gdbpy_initialize_xmethods () < 0 |
1608 | 1611 | || gdbpy_initialize_unwind () < 0) |
@@ -1,3 +1,8 @@ | ||
1 | +2017-09-11 Tom Tromey <tom@tromey.com> | |
2 | + | |
3 | + * gdb.python/py-infthread.exp: Add tests for new_thread event. | |
4 | + * gdb.python/py-inferior.exp: Add tests for new inferior events. | |
5 | + | |
1 | 6 | 2017-09-08 Christoph Weinmann <christoph.t.weinmann@intel.com> |
2 | 7 | |
3 | 8 | * gdb.fortran/printing-types.exp: New file. |
@@ -214,12 +214,33 @@ with_test_prefix "is_valid" { | ||
214 | 214 | gdb_test "python print (inf_list\[0\].is_valid())" "True" \ |
215 | 215 | "check inferior validity 1" |
216 | 216 | |
217 | + gdb_py_test_multiple "install new inferior event handler" \ | |
218 | + "python" "" \ | |
219 | + "my_inferior_count = 1" "" \ | |
220 | + "def new_inf_handler(evt):" "" \ | |
221 | + " global my_inferior_count" "" \ | |
222 | + " if evt.inferior is not None:" "" \ | |
223 | + " my_inferior_count = my_inferior_count + 1" "" \ | |
224 | + "gdb.events.new_inferior.connect(new_inf_handler)" "" \ | |
225 | + "end" "" | |
226 | + gdb_py_test_multiple "install inferior deleted event handler" \ | |
227 | + "python" "" \ | |
228 | + "def del_inf_handler(evt):" "" \ | |
229 | + " global my_inferior_count" "" \ | |
230 | + " if evt.inferior is not None:" "" \ | |
231 | + " my_inferior_count = my_inferior_count - 1" "" \ | |
232 | + "gdb.events.inferior_deleted.connect(del_inf_handler)" "" \ | |
233 | + "end" "" | |
234 | + | |
217 | 235 | gdb_test "add-inferior" "Added inferior 2.*" "add empty inferior 2" |
218 | 236 | gdb_py_test_silent_cmd "python inf_list = gdb.inferiors()" "get new list" 1 |
219 | 237 | gdb_test "python print (len(inf_list))" "2" "get inferior list length 2" |
220 | 238 | gdb_test "python print (inf_list\[0\].is_valid())" "True" \ |
221 | 239 | "check inferior validity 2" |
222 | 240 | |
241 | + gdb_test "python print (my_inferior_count)" "2" \ | |
242 | + "test new-inferior event handler" | |
243 | + | |
223 | 244 | gdb_test "python print (inf_list\[1\].is_valid())" "True" \ |
224 | 245 | "check inferior validity 3" |
225 | 246 |
@@ -229,6 +250,9 @@ with_test_prefix "is_valid" { | ||
229 | 250 | |
230 | 251 | gdb_test "python print (inf_list\[1\].is_valid())" "False" \ |
231 | 252 | "check inferior validity 5" |
253 | + | |
254 | + gdb_test "python print (my_inferior_count)" "1" \ | |
255 | + "test inferior-deleted event handler" | |
232 | 256 | } |
233 | 257 | |
234 | 258 | # Test gdb.selected_inferior() |
@@ -30,6 +30,16 @@ clean_restart ${testfile} | ||
30 | 30 | # Skip all tests if Python scripting is not enabled. |
31 | 31 | if { [skip_python_tests] } { continue } |
32 | 32 | |
33 | +gdb_py_test_multiple "install new_thread event handler" \ | |
34 | + "python" "" \ | |
35 | + "seen_a_thread = False" "" \ | |
36 | + "def thread_handler(evt):" "" \ | |
37 | + " if evt.inferior_thread is not None:" "" \ | |
38 | + " global seen_a_thread" "" \ | |
39 | + " seen_a_thread = True" "" \ | |
40 | + "gdb.events.new_thread.connect(thread_handler)" "" \ | |
41 | + "end" "" | |
42 | + | |
33 | 43 | # The following tests require execution. |
34 | 44 | |
35 | 45 | if ![runto_main] then { |
@@ -37,6 +47,8 @@ if ![runto_main] then { | ||
37 | 47 | return 0 |
38 | 48 | } |
39 | 49 | |
50 | +gdb_test "python print(seen_a_thread)" "True" | |
51 | + | |
40 | 52 | # Test basic gdb.Inferior attributes and methods. |
41 | 53 | |
42 | 54 | gdb_py_test_silent_cmd "python t0 = gdb.selected_thread ()" "test gdb.selected_thread" 1 |