This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Add new_inferior, inferior_deleted, and new_thread events


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=7c96f8c1dae023c7d0b1cabc5e50c4d18fd06960

commit 7c96f8c1dae023c7d0b1cabc5e50c4d18fd06960
Author: Tom Tromey <tom@tromey.com>
Date:   Tue Sep 5 12:07:00 2017 -0600

    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.

Diff:
---
 gdb/ChangeLog                             | 27 ++++++++++
 gdb/NEWS                                  |  6 +++
 gdb/doc/ChangeLog                         |  4 ++
 gdb/doc/python.texi                       | 33 ++++++++++++
 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, 229 insertions(+), 7 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 1781ddd..086fff5 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,30 @@
+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.
+
 2017-09-10  Andrew Burgess  <andrew.burgess@embecosm.com>
 
 	* utils.c (abort_with_message): Don't compare gdb_stderr to NULL,
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..db2f64f 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,7 @@
+2017-09-11  Tom Tromey  <tom@tromey.com>
+
+	* python.texi (Events In Python): Document new events.
+
 2017-09-04  Pedro Alves  <palves@redhat.com>
 
 	* gdb.texinfo (Variables) <Program Variables>: Document inspecting
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index 32d7939..39def2a 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -2989,6 +2989,39 @@ 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 emitted 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 emitted 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 is emitted when @value{GDBN} notices a new thread.  The event is of
+type @code{gdb.NewThreadEvent}, which extends @code{gdb.ThreadEvent}.
+This has a single attribute:
+
+@defvar NewThreadEvent.inferior_thread
+The new thread.
+@end defvar
+
 @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 b086cef..fbb4747 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -1603,6 +1603,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..3862a7c 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+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.
+
 2017-09-08  Christoph Weinmann  <christoph.t.weinmann@intel.com>
 
 	* 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]