From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 38449 invoked by alias); 9 Sep 2017 00:34:05 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 38388 invoked by uid 89); 9 Sep 2017 00:34:04 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.4 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.2 spammy=1992, 2* X-HELO: gproxy2-pub.mail.unifiedlayer.com Received: from gproxy2-pub.mail.unifiedlayer.com (HELO gproxy2-pub.mail.unifiedlayer.com) (69.89.18.3) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 09 Sep 2017 00:34:01 +0000 Received: from cmgw3 (unknown [10.0.90.84]) by gproxy2.mail.unifiedlayer.com (Postfix) with ESMTP id 306351E069C for ; Fri, 8 Sep 2017 18:33:59 -0600 (MDT) Received: from box522.bluehost.com ([74.220.219.122]) by cmgw3 with id 7CZv1w00d2f2jeq01CZyVA; Fri, 08 Sep 2017 18:33:59 -0600 X-Authority-Analysis: v=2.2 cv=K/VSJ2eI c=1 sm=1 tr=0 a=GsOEXm/OWkKvwdLVJsfwcA==:117 a=GsOEXm/OWkKvwdLVJsfwcA==:17 a=2JCJgTwv5E4A:10 a=zstS-IiYAAAA:8 a=20KFwNOVAAAA:8 a=TkTTPzHaAAAA:8 a=QyXUC8HyAAAA:8 a=2nG6T9P4SVfk--a8DiYA:9 a=4G6NA9xxw8l3yy4pmD5M:22 a=Qz3p68GZ3z-NqTySStDO:22 Received: from 75-166-76-94.hlrn.qwest.net ([75.166.76.94]:58502 helo=bapiya.Home) by box522.bluehost.com with esmtpsa (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.87) (envelope-from ) id 1dqTid-000PVl-GB; Fri, 08 Sep 2017 18:33:55 -0600 From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [RFA 1/3] Add new_inferior, inferior_deleted, and new_thread events Date: Sat, 09 Sep 2017 00:34:00 -0000 Message-Id: <20170909003353.25883-2-tom@tromey.com> In-Reply-To: <20170909003353.25883-1-tom@tromey.com> References: <20170909003353.25883-1-tom@tromey.com> X-BWhitelist: no X-Exim-ID: 1dqTid-000PVl-GB X-Source-Sender: 75-166-76-94.hlrn.qwest.net (bapiya.Home) [75.166.76.94]:58502 X-Source-Auth: tom+tromey.com X-Email-Count: 2 X-Source-Cap: ZWx5bnJvYmk7ZWx5bnJvYmk7Ym94NTIyLmJsdWVob3N0LmNvbQ== X-Local-Domain: yes X-SW-Source: 2017-09/txt/msg00217.txt.bz2 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. gdb/ChangeLog 2017-09-08 Tom Tromey 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 fields. * python/py-event.h (create_thread_event_breakpoint): Add optional "thread" parameter. gdb/doc/ChangeLog 2017-09-08 Tom Tromey * python.texi (Events In Python): Document new events. gdb/testsuite/ChangeLog 2017-09-08 Tom Tromey * gdb.python/py-infthread.exp: Add tests for new_thread event. * gdb.python/py-inferior.exp: Add tests for new inferior events. --- gdb/ChangeLog | 27 ++++++++++ gdb/NEWS | 6 +++ gdb/doc/ChangeLog | 6 ++- gdb/doc/python.texi | 30 +++++++++++ gdb/python/py-event.h | 3 +- gdb/python/py-events.h | 3 ++ gdb/python/py-evts.c | 9 ++++ gdb/python/py-inferior.c | 88 +++++++++++++++++++++++++++++++ gdb/python/py-threadevent.c | 13 ++--- gdb/python/python-internal.h | 6 +++ gdb/python/python.c | 3 ++ gdb/testsuite/ChangeLog | 5 ++ gdb/testsuite/gdb.python/py-inferior.exp | 24 +++++++++ gdb/testsuite/gdb.python/py-infthread.exp | 12 +++++ 14 files changed, 227 insertions(+), 8 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 96369d5..88520ea 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,30 @@ +2017-09-08 Tom Tromey + + 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 fields. + * python/py-event.h (create_thread_event_breakpoint): Add optional + "thread" parameter. + 2017-09-08 Keith Seitz * dwarf2read.c (struct field_info) : Remove unused diff --git a/gdb/NEWS b/gdb/NEWS index f6ed614..2e6d48c 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -15,6 +15,12 @@ the remote inferior is started by the GDBserver, use the "unset environment" command. +* Python Scripting + + ** New events gdb.new_inferior, gdb.inferior_deleted, and + gdb.new_thread are emitted. See the manual for further + description of these. + * New features in the GDB remote stub, GDBserver ** New "--selftest" command line option runs some GDBserver self diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 72f3d9e..65147f7 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2017-09-08 Tom Tromey + + * python.texi (Events In Python): Document new events. + 2017-09-04 Pedro Alves * gdb.texinfo (Variables) : Document inspecting @@ -12039,7 +12043,7 @@ Wed Feb 26 18:04:40 1992 K. Richard Pixley (rich@cygnus.com) * Makefile.in, configure.in: removed traces of namesubdir, -subdirs, $(subdir), $(unsubdir), some rcs triggers. Forced - copyrights to '92, '13, changed some from Cygnus to FSF. + copyrights to '92, '13, '17, changed some from Cygnus to FSF. Fri Dec 13 09:47:31 1991 John Gilmore (gnu at cygnus.com) diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 32d7939..83d078b 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -2989,6 +2989,36 @@ invalid state; that is, the @code{is_valid} method will return This event carries no payload. It is emitted each time @value{GDBN} presents a prompt to the user. +@item events.new_inferior +This is notified when a new inferior is created. Note that the +inferior is not necessarily running; in fact, it may not even have an +associated executable. + +The event is of type @code{gdb.NewInferiorEvent}. This has a single +attribute: + +@defvar NewInferiorEvent.inferior +The new inferior, a @code{gdb.Inferior} object. +@end defvar + +@item events.inferior_deleted +This is notified when an inferior has been deleted. Note that this is +not the same as process exit; it is notified when the inferior itself +is removed, say via @code{remove-inferiors}. + +The event is of type @code{gdb.InferiorDeletedEvent}. This has a single +attribute: + +@defvar NewInferiorEvent.inferior +The inferior that is being removed, a @code{gdb.Inferior} object. +@end defvar + +@item events.new_thread +This emitted when @value{GDBN} notices a new thread. The event is of +type @code{gdb.NewThreadEvent}, which extends @code{gdb.ThreadEvent}. +The @code{new_thread} event always sets the @code{inferior_thread} +attribute on the event object, regardless of the non-stop setting. + @end table @node Threads In Python diff --git a/gdb/python/py-event.h b/gdb/python/py-event.h index ccb8513..2f02c5f 100644 --- a/gdb/python/py-event.h +++ b/gdb/python/py-event.h @@ -125,7 +125,8 @@ extern int evpy_emit_event (PyObject *event, eventregistry_object *registry); extern PyObject *create_event_object (PyTypeObject *py_type); -extern PyObject *create_thread_event_object (PyTypeObject *py_type); +extern PyObject *create_thread_event_object (PyTypeObject *py_type, + PyObject *thread = nullptr); extern int emit_new_objfile_event (struct objfile *objfile); extern int emit_clear_objfiles_event (void); diff --git a/gdb/python/py-events.h b/gdb/python/py-events.h index 348dabc..2275d89 100644 --- a/gdb/python/py-events.h +++ b/gdb/python/py-events.h @@ -47,6 +47,9 @@ typedef struct eventregistry_object *exited; eventregistry_object *new_objfile; eventregistry_object *clear_objfiles; + eventregistry_object *new_inferior; + eventregistry_object *inferior_deleted; + eventregistry_object *new_thread; eventregistry_object *inferior_call; eventregistry_object *memory_changed; eventregistry_object *register_changed; diff --git a/gdb/python/py-evts.c b/gdb/python/py-evts.c index 126d18c..ad99241 100644 --- a/gdb/python/py-evts.c +++ b/gdb/python/py-evts.c @@ -89,6 +89,15 @@ 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.new_inferior, "new_inferior") < 0) + return -1; + + if (add_new_registry (&gdb_py_events.inferior_deleted, "inferior_deleted") < 0) + return -1; + + if (add_new_registry (&gdb_py_events.new_thread, "new_thread") < 0) + return -1; + if (add_new_registry (&gdb_py_events.breakpoint_created, "breakpoint_created") < 0) return -1; diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c index f6a24a0..d7c6810 100644 --- a/gdb/python/py-inferior.c +++ b/gdb/python/py-inferior.c @@ -30,6 +30,13 @@ #include "py-event.h" #include "py-stopevent.h" +extern PyTypeObject new_thread_event_object_type + CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object"); +extern PyTypeObject new_inferior_event_object_type + CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object"); +extern PyTypeObject inferior_deleted_event_object_type + CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object"); + struct threadlist_entry { thread_object *thread_obj; struct threadlist_entry *next; @@ -235,6 +242,60 @@ inferior_to_inferior_object (struct inferior *inferior) return (PyObject *) inf_obj; } +/* Called when a new inferior is created. Notifies any Python event + listeners. */ +static void +python_new_inferior (struct inferior *inf) +{ + if (!gdb_python_initialized) + return; + + gdbpy_enter enter_py (python_gdbarch, python_language); + + if (evregpy_no_listeners_p (gdb_py_events.new_inferior)) + return; + + gdbpy_ref<> inf_obj (inferior_to_inferior_object (inf)); + if (inf_obj == NULL) + { + gdbpy_print_stack (); + return; + } + + gdbpy_ref<> event (create_event_object (&new_inferior_event_object_type)); + if (event == NULL + || evpy_add_attribute (event.get (), "inferior", inf_obj.get ()) < 0 + || evpy_emit_event (event.get (), gdb_py_events.new_inferior) < 0) + gdbpy_print_stack (); +} + +/* Called when an inferior is removed. Notifies any Python event + listeners. */ +static void +python_inferior_deleted (struct inferior *inf) +{ + if (!gdb_python_initialized) + return; + + gdbpy_enter enter_py (python_gdbarch, python_language); + + if (evregpy_no_listeners_p (gdb_py_events.inferior_deleted)) + return; + + gdbpy_ref<> inf_obj (inferior_to_inferior_object (inf)); + if (inf_obj == NULL) + { + gdbpy_print_stack (); + return; + } + + gdbpy_ref<> event (create_event_object (&inferior_deleted_event_object_type)); + if (event == NULL + || evpy_add_attribute (event.get (), "inferior", inf_obj.get ()) < 0 + || evpy_emit_event (event.get (), gdb_py_events.inferior_deleted) < 0) + gdbpy_print_stack (); +} + /* Finds the Python Inferior object for the given PID. Returns a reference, or NULL if PID does not match any inferior object. */ @@ -298,6 +359,15 @@ add_thread_object (struct thread_info *tp) inf_obj->threads = entry; inf_obj->nthreads++; + + if (evregpy_no_listeners_p (gdb_py_events.new_thread)) + return; + + gdbpy_ref<> event (create_thread_event_object (&new_thread_event_object_type, + (PyObject *) thread_obj)); + if (event == NULL + || evpy_emit_event (event.get (), gdb_py_events.new_thread) < 0) + gdbpy_print_stack (); } static void @@ -823,6 +893,8 @@ gdbpy_initialize_inferior (void) observer_attach_register_changed (python_on_register_change); observer_attach_inferior_exit (python_inferior_exit); observer_attach_new_objfile (python_new_objfile); + observer_attach_inferior_added (python_new_inferior); + observer_attach_inferior_removed (python_inferior_deleted); membuf_object_type.tp_new = PyType_GenericNew; if (PyType_Ready (&membuf_object_type) < 0) @@ -970,3 +1042,19 @@ PyTypeObject membuf_object_type = { 0, /* tp_init */ 0, /* tp_alloc */ }; + +GDBPY_NEW_EVENT_TYPE (new_thread, + "gdb.NewThreadEvent", + "NewThreadEvent", + "GDB new thread event object", + thread_event_object_type); +GDBPY_NEW_EVENT_TYPE (new_inferior, + "gdb.NewInferiorEvent", + "NewInferiorEvent", + "GDB new inferior event object", + event_object_type); +GDBPY_NEW_EVENT_TYPE (inferior_deleted, + "gdb.InferiorDeletedEvent", + "InferiorDeletedEvent", + "GDB inferior deleted event object", + event_object_type); diff --git a/gdb/python/py-threadevent.c b/gdb/python/py-threadevent.c index 9217444..7211fa2 100644 --- a/gdb/python/py-threadevent.c +++ b/gdb/python/py-threadevent.c @@ -48,17 +48,18 @@ get_event_thread (void) } PyObject * -create_thread_event_object (PyTypeObject *py_type) +create_thread_event_object (PyTypeObject *py_type, PyObject *thread) { - PyObject *thread = NULL; - gdbpy_ref<> thread_event_obj (create_event_object (py_type)); if (thread_event_obj == NULL) return NULL; - thread = get_event_thread (); - if (!thread) - return NULL; + if (thread == NULL) + { + thread = get_event_thread (); + if (!thread) + return NULL; + } if (evpy_add_attribute (thread_event_obj.get (), "inferior_thread", diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index ebb83f0..0c3582f 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -630,6 +630,12 @@ int gdbpy_initialize_new_objfile_event (void) CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; int gdbpy_initialize_clear_objfiles_event (void) CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; +int gdbpy_initialize_new_inferior_event (void) + CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; +int gdbpy_initialize_inferior_deleted_event (void) + CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; +int gdbpy_initialize_new_thread_event (void) + CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; int gdbpy_initialize_arch (void) CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; int gdbpy_initialize_xmethods (void) diff --git a/gdb/python/python.c b/gdb/python/python.c index f40fe89..7ff84e4 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -1609,6 +1609,9 @@ do_start_initialization () || gdbpy_initialize_thread_event () < 0 || gdbpy_initialize_new_objfile_event () < 0 || gdbpy_initialize_clear_objfiles_event () < 0 + || gdbpy_initialize_new_inferior_event () < 0 + || gdbpy_initialize_inferior_deleted_event () < 0 + || gdbpy_initialize_new_thread_event () < 0 || gdbpy_initialize_arch () < 0 || gdbpy_initialize_xmethods () < 0 || gdbpy_initialize_unwind () < 0) diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 8d8dc3c..e982684 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-09-08 Tom Tromey + + * gdb.python/py-infthread.exp: Add tests for new_thread event. + * gdb.python/py-inferior.exp: Add tests for new inferior events. + 2017-09-08 Christoph Weinmann * gdb.fortran/printing-types.exp: New file. diff --git a/gdb/testsuite/gdb.python/py-inferior.exp b/gdb/testsuite/gdb.python/py-inferior.exp index c2ea2c2..715c693 100644 --- a/gdb/testsuite/gdb.python/py-inferior.exp +++ b/gdb/testsuite/gdb.python/py-inferior.exp @@ -214,12 +214,33 @@ with_test_prefix "is_valid" { gdb_test "python print (inf_list\[0\].is_valid())" "True" \ "check inferior validity 1" + gdb_py_test_multiple "install new inferior event handler" \ + "python" "" \ + "my_inferior_count = 1" "" \ + "def new_inf_handler(evt):" "" \ + " global my_inferior_count" "" \ + " if evt.inferior is not None:" "" \ + " my_inferior_count = my_inferior_count + 1" "" \ + "gdb.events.new_inferior.connect(new_inf_handler)" "" \ + "end" "" + gdb_py_test_multiple "install inferior deleted event handler" \ + "python" "" \ + "def del_inf_handler(evt):" "" \ + " global my_inferior_count" "" \ + " if evt.inferior is not None:" "" \ + " my_inferior_count = my_inferior_count - 1" "" \ + "gdb.events.inferior_deleted.connect(del_inf_handler)" "" \ + "end" "" + gdb_test "add-inferior" "Added inferior 2.*" "add empty inferior 2" gdb_py_test_silent_cmd "python inf_list = gdb.inferiors()" "get new list" 1 gdb_test "python print (len(inf_list))" "2" "get inferior list length 2" gdb_test "python print (inf_list\[0\].is_valid())" "True" \ "check inferior validity 2" + gdb_test "python print (my_inferior_count)" "2" \ + "test new-inferior event handler" + gdb_test "python print (inf_list\[1\].is_valid())" "True" \ "check inferior validity 3" @@ -229,6 +250,9 @@ with_test_prefix "is_valid" { gdb_test "python print (inf_list\[1\].is_valid())" "False" \ "check inferior validity 5" + + gdb_test "python print (my_inferior_count)" "1" \ + "test inferior-deleted event handler" } # Test gdb.selected_inferior() diff --git a/gdb/testsuite/gdb.python/py-infthread.exp b/gdb/testsuite/gdb.python/py-infthread.exp index a5fed8d..0711d69 100644 --- a/gdb/testsuite/gdb.python/py-infthread.exp +++ b/gdb/testsuite/gdb.python/py-infthread.exp @@ -30,6 +30,16 @@ clean_restart ${testfile} # Skip all tests if Python scripting is not enabled. if { [skip_python_tests] } { continue } +gdb_py_test_multiple "install new_thread event handler" \ + "python" "" \ + "seen_a_thread = False" "" \ + "def thread_handler(evt):" "" \ + " if evt.inferior_thread is not None:" "" \ + " global seen_a_thread" "" \ + " seen_a_thread = True" "" \ + "gdb.events.new_thread.connect(thread_handler)" "" \ + "end" "" + # The following tests require execution. if ![runto_main] then { @@ -37,6 +47,8 @@ if ![runto_main] then { return 0 } +gdb_test "python print(seen_a_thread)" "True" + # Test basic gdb.Inferior attributes and methods. gdb_py_test_silent_cmd "python t0 = gdb.selected_thread ()" "test gdb.selected_thread" 1 -- 2.9.4