public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Andrew Burgess <aburgess@redhat.com>
To: gdb-patches@sourceware.org
Cc: Andrew Burgess <aburgess@redhat.com>
Subject: [PATCH 6/6] gdb/python: Add gdb.InferiorThread.__dict__ attribute
Date: Fri,  5 Jan 2024 11:48:35 +0000	[thread overview]
Message-ID: <6fdf97c5f147a7e71fc0ca4de9e49961c067bae1.1704455158.git.aburgess@redhat.com> (raw)
In-Reply-To: <cover.1704455158.git.aburgess@redhat.com>

The gdb.Objfile, gdb.Progspace, gdb.Type, and gdb.Inferior Python
types already have a __dict__ attribute, which allows users to create
user defined attributes within the objects.  This is useful if the
user wants to cache information within an object.

This commit adds the same functionality to the gdb.InferiorThread
type.

After this commit there is a new gdb.InferiorThread.__dict__
attribute, which is a dictionary.  A user can, for example, do this:

  (gdb) pi
  >>> t = gdb.selected_thread()
  >>> t._user_attribute = 123
  >>> t._user_attribute
  123
  >>>

There's a new test included.
---
 gdb/NEWS                                 |  4 +++
 gdb/doc/python.texi                      | 31 ++++++++++++++++++++++++
 gdb/python/py-infthread.c                | 17 +++++++++++--
 gdb/python/python-internal.h             |  4 +++
 gdb/testsuite/gdb.python/py-inferior.exp | 17 +++++++++++++
 5 files changed, 71 insertions(+), 2 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 500d5ab7160..c4862a8beb6 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -96,6 +96,10 @@ show remote thread-options-packet
      these will be stored in the object's new Inferior.__dict__
      attribute.
 
+  ** User defined attributes can be added to a gdb.InferiorThread
+     object, these will be stored in the object's new
+     InferiorThread.__dict__ attribute.
+
 * Debugger Adapter Protocol changes
 
   ** GDB now emits the "process" event.
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index 721f0100178..ecba7cfa89c 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -4173,6 +4173,37 @@
 a @code{gdb.Type} for the handle type.
 @end defun
 
+One may add arbitrary attributes to @code{gdb.InferiorThread} objects
+in the usual Python way.  This is useful if, for example, one needs to
+do some extra record keeping associated with the thread.
+
+In this contrived example we record the time when a thread last
+stopped:
+
+@smallexample
+(gdb) python
+import datetime
+
+def thread_stopped(event):
+    if event.inferior_thread is not None:
+        thread = event.inferior_thread
+    else:
+        thread = gdb.selected_thread()
+    thread._last_stop_time = datetime.datetime.today()
+
+gdb.events.stop.connect(thread_stopped)
+(gdb) file /tmp/hello
+Reading symbols from /tmp/hello...
+(gdb) start
+Temporary breakpoint 1 at 0x401198: file /tmp/hello.c, line 18.
+Starting program: /tmp/hello
+
+Temporary breakpoint 1, main () at /tmp/hello.c:18
+18	  printf ("Hello World\n");
+(gdb) python print(gdb.selected_thread()._last_stop_time)
+2024-01-04 14:48:41.347036
+@end smallexample
+
 @node Recordings In Python
 @subsubsection Recordings In Python
 @cindex recordings in python
diff --git a/gdb/python/py-infthread.c b/gdb/python/py-infthread.c
index 2d892b10b69..fa24ef3b9ca 100644
--- a/gdb/python/py-infthread.c
+++ b/gdb/python/py-infthread.c
@@ -49,6 +49,10 @@ create_thread_object (struct thread_info *tp)
   if (thread_obj == NULL)
     return NULL;
 
+  thread_obj->dict = PyDict_New ();
+  if (thread_obj->dict == nullptr)
+    return nullptr;
+
   thread_obj->thread = tp;
   thread_obj->inf_obj = (PyObject *) inf_obj.release ();
 
@@ -58,7 +62,14 @@ create_thread_object (struct thread_info *tp)
 static void
 thpy_dealloc (PyObject *self)
 {
-  Py_DECREF (((thread_object *) self)->inf_obj);
+  thread_object *thr_obj = (thread_object *) self;
+
+  gdb_assert (thr_obj->inf_obj != nullptr);
+  gdb_assert (thr_obj->dict != nullptr);
+
+  Py_DECREF (thr_obj->inf_obj);
+  Py_DECREF (thr_obj->dict);
+
   Py_TYPE (self)->tp_free (self);
 }
 
@@ -394,6 +405,8 @@ GDBPY_INITIALIZE_FILE (gdbpy_initialize_thread);
 
 static gdb_PyGetSetDef thread_object_getset[] =
 {
+  { "__dict__", gdb_py_generic_dict, nullptr,
+    "The __dict__ for this thread.", &thread_object_type },
   { "name", thpy_get_name, thpy_set_name,
     "The name of the thread, as set by the user or the OS.", NULL },
   { "details", thpy_get_details, NULL,
@@ -471,7 +484,7 @@ PyTypeObject thread_object_type =
   0,				  /* tp_dict */
   0,				  /* tp_descr_get */
   0,				  /* tp_descr_set */
-  0,				  /* tp_dictoffset */
+  offsetof (thread_object, dict), /* tp_dictoffset */
   0,				  /* tp_init */
   0				  /* tp_alloc */
 };
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 8ff9af650c2..e01557edeb7 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -356,6 +356,10 @@ struct thread_object
 
   /* The Inferior object to which this thread belongs.  */
   PyObject *inf_obj;
+
+  /* Dictionary holding user-added attributes.  This is the __dict__
+     attribute of the object.  */
+  PyObject *dict;
 };
 
 struct inferior_object;
diff --git a/gdb/testsuite/gdb.python/py-inferior.exp b/gdb/testsuite/gdb.python/py-inferior.exp
index 0e00636fa1c..d1cd29f734b 100644
--- a/gdb/testsuite/gdb.python/py-inferior.exp
+++ b/gdb/testsuite/gdb.python/py-inferior.exp
@@ -107,6 +107,19 @@ gdb_test "python print(last_thread)" \
     "<gdb.InferiorThread id=${decimal}\\.${decimal} target-id=\"\[^\r\n\]*\">" \
     "test repr of a valid thread"
 
+# Add a user defined attribute to this thread, check the attribute can
+# be read back, and check the attribute is not present on other
+# threads.
+gdb_test_no_output "python last_thread._user_attribute = 123" \
+    "add user defined attribute to InferiorThread object"
+gdb_test "python print(last_thread._user_attribute)" "123" \
+    "read back user defined attribute"
+gdb_test "python print(i0.threads ()\[0\]._user_attribute)" \
+    [multi_line \
+	 "AttributeError: 'gdb\\.InferiorThread' object has no attribute '_user_attribute'" \
+	 "Error while executing Python code\\."] \
+    "attempt to read non-existent user defined attribute"
+
 # Proceed to the next test.
 
 gdb_breakpoint [gdb_get_line_number "Break here."]
@@ -117,6 +130,10 @@ gdb_test "python print(last_thread)" \
     "<gdb.InferiorThread \\(invalid\\)>" \
     "test repr of an invalid thread"
 
+# Check the user defined attribute is still present on the invalid thread object.
+gdb_test "python print(last_thread._user_attribute)" "123" \
+    "check user defined attribute on an invalid InferiorThread object"
+
 # Test memory read and write operations.
 
 gdb_py_test_silent_cmd "python addr = gdb.selected_frame ().read_var ('str')" \
-- 
2.25.4


  parent reply	other threads:[~2024-01-05 11:48 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-05 11:48 [PATCH 0/6] Python __repr__() methods and new __dict__ attributes Andrew Burgess
2024-01-05 11:48 ` [PATCH 1/6] gdb/python: hoist common invalid object repr code into py-utils.c Andrew Burgess
2024-01-09 19:19   ` Tom Tromey
2024-01-05 11:48 ` [PATCH 2/6] gdb/python: add gdb.InferiorThread.__repr__() method Andrew Burgess
2024-01-05 11:48 ` [PATCH 3/6] gdb/python: add gdb.Frame.__repr__() method Andrew Burgess
2024-01-05 11:48 ` [PATCH 4/6] gdb/python: remove users ability to create gdb.Progspace objects Andrew Burgess
2024-01-05 13:27   ` Eli Zaretskii
2024-01-05 11:48 ` [PATCH 5/6] gdb/python: Add gdb.Inferior.__dict__ attribute Andrew Burgess
2024-01-05 13:33   ` Eli Zaretskii
2024-01-09 20:05   ` Tom Tromey
2024-01-05 11:48 ` Andrew Burgess [this message]
2024-01-05 13:31   ` [PATCH 6/6] gdb/python: Add gdb.InferiorThread.__dict__ attribute Eli Zaretskii
2024-01-09 20:11   ` Tom Tromey
2024-01-10 10:38     ` Andrew Burgess
2024-01-10 15:54 ` [PATCHv2 0/8] Python __repr__() methods and new __dict__ attributes Andrew Burgess
2024-01-09 17:32   ` [PATCH] gdb/python: New InferiorThread.ptid_string attribute Andrew Burgess
2024-01-09 18:50     ` Eli Zaretskii
2024-01-09 19:10     ` Tom Tromey
2024-01-12  9:39       ` [PUSHED] " Andrew Burgess
2024-01-10 15:54     ` [PATCH] " Andrew Burgess
2024-01-10 15:54   ` [PATCHv2 1/8] gdb/python: hoist common invalid object repr code into py-utils.c Andrew Burgess
2024-01-10 15:54   ` [PATCHv2 2/8] gdb/python: add gdb.InferiorThread.__repr__() method Andrew Burgess
2024-01-10 15:54   ` [PATCHv2 3/8] gdb/python: add gdb.Frame.__repr__() method Andrew Burgess
2024-01-10 15:54   ` [PATCHv2 4/8] gdb/python: remove users ability to create gdb.Progspace objects Andrew Burgess
2024-01-10 15:54   ` [PATCHv2 5/8] gdb/python: Add gdb.Inferior.__dict__ attribute Andrew Burgess
2024-01-10 15:54   ` [PATCHv2 6/8] gdb/python: Add gdb.InferiorThread.__dict__ attribute Andrew Burgess
2024-01-10 15:54   ` [PATCHv2 7/8] gdb/doc: add some notes on selecting suitable attribute names Andrew Burgess
2024-01-10 16:35     ` Eli Zaretskii
2024-01-11 10:48       ` Andrew Burgess
2024-01-11 10:56         ` Eli Zaretskii
2024-01-10 15:54   ` [PATCHv2 8/8] gdb/doc: update examples in gdb.Progspace and gdb.Objfile docs Andrew Burgess
2024-01-10 16:36     ` Eli Zaretskii
2024-01-10 18:08   ` [PATCHv2 0/8] Python __repr__() methods and new __dict__ attributes Tom Tromey
2024-01-12 13:44     ` Andrew Burgess
2024-01-12 14:57       ` Tom de Vries
2024-01-12 16:20         ` Andrew Burgess

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6fdf97c5f147a7e71fc0ca4de9e49961c067bae1.1704455158.git.aburgess@redhat.com \
    --to=aburgess@redhat.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).