Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Tom Tromey <tom@tromey.com>
To: gdb-patches@sourceware.org
Cc: Tom Tromey <tom@tromey.com>
Subject: [PATCH 2/4] Convert gdbpy_newest_frame and gdbpy_selected_frame to safety API
Date: Wed, 19 Aug 2026 17:54:40 -0600	[thread overview]
Message-ID: <20260819-python-safety-frame-v1-2-563cb6b9e7a6@tromey.com> (raw)
In-Reply-To: <20260819-python-safety-frame-v1-0-563cb6b9e7a6@tromey.com>

This convert gdbpy_newest_frame and gdbpy_selected_frame to the Python
safety API.  Some extra work was needed in py-inferior.c; note that
the code there is "temporary" -- once event emission is converted, the
try/catch can be removed.  Also, a new noargs_function wrapper was
needed.
---
 gdb/python/py-frame.c        | 44 ++++++++++++++++----------------------------
 gdb/python/py-inferior.c     | 24 ++++++++++++++++++------
 gdb/python/py-safety.h       | 21 +++++++++++++++++++++
 gdb/python/python-internal.h |  4 ++--
 gdb/python/python.c          |  8 ++++----
 5 files changed, 61 insertions(+), 40 deletions(-)

diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c
index 5c5ff8cf0de..3910f19ef83 100644
--- a/gdb/python/py-frame.c
+++ b/gdb/python/py-frame.c
@@ -438,41 +438,29 @@ frame_object::static_link ()
 /* Implementation of gdb.newest_frame () -> gdb.Frame.
    Returns the newest frame object.  */
 
-PyObject *
-gdbpy_newest_frame (PyObject *self, PyObject *args)
+gdbpy_ref<>
+gdbpy_newest_frame ()
 {
-  frame_info_ptr frame = NULL;
-
-  try
-    {
-      frame = get_current_frame ();
-    }
-  catch (const gdb_exception &except)
-    {
-      return gdbpy_handle_gdb_exception (nullptr, except);
-    }
-
-  return frame_info_to_frame_object (frame).release ();
+  /* FIXME: Python safety.  Convert frame_info_to_frame_object.  */
+  gdbpy_ref<> result = frame_info_to_frame_object (get_current_frame ());
+  if (result == nullptr)
+    throw gdb_python_exception ();
+  return result;
 }
 
 /* Implementation of gdb.selected_frame () -> gdb.Frame.
    Returns the selected frame object.  */
 
-PyObject *
-gdbpy_selected_frame (PyObject *self, PyObject *args)
+gdbpy_ref<>
+gdbpy_selected_frame ()
 {
-  frame_info_ptr frame = NULL;
-
-  try
-    {
-      frame = get_selected_frame ("No frame is currently selected.");
-    }
-  catch (const gdb_exception &except)
-    {
-      return gdbpy_handle_gdb_exception (nullptr, except);
-    }
-
-  return frame_info_to_frame_object (frame).release ();
+  frame_info_ptr frame
+    = get_selected_frame ("No frame is currently selected.");
+  /* FIXME: Python safety.  Convert frame_info_to_frame_object.  */
+  gdbpy_ref<> result = frame_info_to_frame_object (frame);
+  if (result == nullptr)
+    throw gdb_python_exception ();
+  return result;
 }
 
 /* Implementation of gdb.stop_reason_string (Integer) -> String.
diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c
index 426aec31e9e..780f7271c09 100644
--- a/gdb/python/py-inferior.c
+++ b/gdb/python/py-inferior.c
@@ -1023,13 +1023,25 @@ python_context_changed (user_selected_what selection)
     }
 
   gdbpy_ref<> frame_obj;
-  if (has_stack_frames ())
-    frame_obj = gdbpy_ref<> (gdbpy_selected_frame (nullptr, nullptr));
-  else
-    frame_obj = py_none ();
-
-  if (frame_obj == nullptr)
+  /* FIXME: Python safety.  Eventually this function will be converted
+     and this try/catch can be removed.  */
+  try
+    {
+      if (has_stack_frames ())
+	frame_obj = gdbpy_selected_frame ();
+      else
+	frame_obj = py_none ();
+    }
+  catch (const gdb_python_exception &e)
+    {
+      gdbpy_print_stack ();
+      return;
+    }
+  catch (const gdb_exception &exc)
     {
+      /* This is a bit roundabout but we're going to be deleting this
+	 code someday anyway.  */
+      (void) gdbpy_handle_gdb_exception (nullptr, exc);
       gdbpy_print_stack ();
       return;
     }
diff --git a/gdb/python/py-safety.h b/gdb/python/py-safety.h
index 3294f38c8b6..06324868817 100644
--- a/gdb/python/py-safety.h
+++ b/gdb/python/py-safety.h
@@ -233,6 +233,27 @@ varargs_wrapper (PyObject *self, PyObject *args, PyObject *kw)
 
 } /* namespace safety_details */
 
+/* Create a PyMethodDef for a no-argument function.  It takes the
+   underlying function F as template parameters, and the name and
+   documentation as arguments.  The function F is wrapped to call
+   to_python and to catch exceptions per the safety protocol.  F
+   should not accept any arguments.  */
+template<auto F>
+constexpr PyMethodDef
+noargs_function (const char *name, const char *doc)
+{
+  using namespace safety_details;
+  return {
+    name,
+    [] (PyObject *self, PyObject *args) -> PyObject *
+    {
+      return wrapped_function<F> ();
+    },
+    METH_NOARGS,
+    doc,
+  };
+}
+
 /* Create a PyMethodDef for a no-argument method.  It takes the
    underlying class C and a pointer-to-method M as template
    parameters, and the name and documentation as arguments.  The
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 5529e9fd4d7..76ccdc6b0c6 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -477,8 +477,8 @@ gdbpy_ref<> gdbpy_lookup_static_symbols (gdbpy_borrowed_ref<> args,
 PyObject *gdbpy_start_recording (PyObject *self, PyObject *args);
 PyObject *gdbpy_current_recording (PyObject *self, PyObject *args);
 PyObject *gdbpy_stop_recording (PyObject *self, PyObject *args);
-PyObject *gdbpy_newest_frame (PyObject *self, PyObject *args);
-PyObject *gdbpy_selected_frame (PyObject *self, PyObject *args);
+gdbpy_ref<> gdbpy_newest_frame ();
+gdbpy_ref<> gdbpy_selected_frame ();
 PyObject *gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw);
 int gdbpy_is_field (PyObject *obj);
 PyObject *gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 14c243b135e..72c2d7bb10d 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -3159,12 +3159,12 @@ Arguments (also strings) are passed to the command." },
   { "current_objfile", gdbpy_get_current_objfile, METH_NOARGS,
     "Return the current Objfile being loaded, or None." },
 
-  { "newest_frame", gdbpy_newest_frame, METH_NOARGS,
+  noargs_function<gdbpy_newest_frame> ("newest_frame",
     "newest_frame () -> gdb.Frame.\n\
-Return the newest frame object." },
-  { "selected_frame", gdbpy_selected_frame, METH_NOARGS,
+Return the newest frame object."),
+  noargs_function<gdbpy_selected_frame> ("selected_frame",
     "selected_frame () -> gdb.Frame.\n\
-Return the selected frame object." },
+Return the selected frame object."),
   { "frame_stop_reason_string", gdbpy_frame_stop_reason_string, METH_VARARGS,
     "stop_reason_string (Integer) -> String.\n\
 Return a string explaining unwind stop reason." },

-- 
2.49.0


  parent reply	other threads:[~2026-08-19 23:56 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-19 23:54 [PATCH 0/4] Convert py-frame.c to Python " Tom Tromey
2026-08-19 23:54 ` [PATCH 1/4] Basic safety conversion of py-frame.c Tom Tromey
2026-08-19 23:54 ` Tom Tromey [this message]
2026-08-19 23:54 ` [PATCH 3/4] Convert gdbpy_frame_stop_reason_string to the safety API Tom Tromey
2026-08-19 23:54 ` [PATCH 4/4] Convert frapy_richcompare to " Tom Tromey

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=20260819-python-safety-frame-v1-2-563cb6b9e7a6@tromey.com \
    --to=tom@tromey.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