public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/3] New mechanism to initialise Python components in GDB
@ 2022-10-02 16:53 Andrew Burgess
  2022-10-02 16:53 ` [PATCH 1/3] gdb/python: break dependencies between gdbpy_initialize_* functions Andrew Burgess
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Andrew Burgess @ 2022-10-02 16:53 UTC (permalink / raw)
  To: gdb-patches

This series is a rewrite of how we initialise Python components within
GDB.  Patch #3 is where the actual change took place.

Patches #1 and #2 relate to dependencies between different Python
components.  Currently there are two pairs of components that have an
initialisation order dependency.  The change I propose in patch #3
revealed these dependencies which I think are otherwise pretty hidden.
In patches #1 and #2 I've tweaked things so these dependencies are now
(I think) more explicit.

This is a pure refactoring project.  I've had a rough outline of patch
#3 kicking about for a while, but I recently thought I would need to
add a new Python component finalize function (similar to
gdbpy_finalize_micommands), so took the time to finish this series
off...

... then it turned out I didn't need to add a new finalize function at
all.

Personally, I think this is an improvement, so I'm posting it, but I'd
love to hear others thoughts.

Thanks,
Andrew

---

Andrew Burgess (3):
  gdb/python: break dependencies between gdbpy_initialize_* functions
  gdb/python: break more dependencies between gdbpy_initialize_*
    functions
  gdb/python: add gdbpy_register_subsystem mechanism

 gdb/python/py-arch.c             |  11 ++-
 gdb/python/py-auto-load.c        |   9 ++-
 gdb/python/py-block.c            |   9 ++-
 gdb/python/py-breakpoint.c       |  30 ++++++--
 gdb/python/py-cmd.c              |   9 ++-
 gdb/python/py-connection.c       |   4 +-
 gdb/python/py-disasm.c           |  11 ++-
 gdb/python/py-event.c            |   9 ++-
 gdb/python/py-evtregistry.c      |   9 ++-
 gdb/python/py-finishbreakpoint.c |  14 +++-
 gdb/python/py-frame.c            |   9 ++-
 gdb/python/py-function.c         |   9 ++-
 gdb/python/py-gdb-readline.c     |  10 ++-
 gdb/python/py-inferior.c         |  11 ++-
 gdb/python/py-infthread.c        |  11 ++-
 gdb/python/py-instruction.c      |  50 +++++++++++---
 gdb/python/py-instruction.h      |  13 ++--
 gdb/python/py-lazy-string.c      |   9 ++-
 gdb/python/py-linetable.c        |   9 ++-
 gdb/python/py-membuf.c           |  11 ++-
 gdb/python/py-micmd.c            |   9 ++-
 gdb/python/py-objfile.c          |   9 ++-
 gdb/python/py-param.c            |   9 ++-
 gdb/python/py-progspace.c        |   9 ++-
 gdb/python/py-record-btrace.c    |   9 ++-
 gdb/python/py-record.c           |  11 ++-
 gdb/python/py-registers.c        |  11 ++-
 gdb/python/py-symbol.c           |   9 ++-
 gdb/python/py-symtab.c           |   9 ++-
 gdb/python/py-tui.c              |   9 ++-
 gdb/python/py-type.c             |   9 ++-
 gdb/python/py-unwind.c           |  34 +++++----
 gdb/python/py-value.c            |   9 ++-
 gdb/python/py-xmethods.c         |   9 ++-
 gdb/python/python-internal.h     | 114 ++++++++++++-------------------
 gdb/python/python.c              |  73 ++++++++++----------
 36 files changed, 427 insertions(+), 172 deletions(-)

-- 
2.25.4


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/3] gdb/python: break dependencies between gdbpy_initialize_* functions
  2022-10-02 16:53 [PATCH 0/3] New mechanism to initialise Python components in GDB Andrew Burgess
@ 2022-10-02 16:53 ` Andrew Burgess
  2022-10-14 17:06   ` Tom Tromey
  2022-10-02 16:53 ` [PATCH 2/3] gdb/python: break more " Andrew Burgess
  2022-10-02 16:53 ` [PATCH 3/3] gdb/python: add gdbpy_register_subsystem mechanism Andrew Burgess
  2 siblings, 1 reply; 13+ messages in thread
From: Andrew Burgess @ 2022-10-02 16:53 UTC (permalink / raw)
  To: gdb-patches

In a later commit in this series I will propose removing all of the
explicit gdbpy_initialize_* calls from python.c and replace these
calls with a more generic mechanism.

One of the side effects of this generic mechanism is that the order in
which the various Python sub-systems within GDB are initialized is no
longer guaranteed.

On the whole I don't think this matters, most of the sub-systems are
independent of each other, though testing did reveal a few places
where we did have dependencies, though I don't think those
dependencies were explicitly documented in a comment anywhere.

This commit removes the first dependency issue, with this and the next
commit, all of the implicit inter-sub-system dependencies will be
replaced by explicit dependencies, which will allow me to, I think,
clean up how the sub-systems are initialized.

The dependency is around the py_insn_type.  This type is setup in
gdbpy_initialize_instruction and used in gdbpy_initialize_record.
Rather than depend on the calls to these two functions being in a
particular order, in this commit I propose adding a new function
py_insn_get_insn_type.  This function will take care of setting up the
py_insn_type type and calling PyType_Ready.  This helper function can
be called from gdbpy_initialize_record and
gdbpy_initialize_instruction, and the py_insn_type will be initialized
just once.

To me this is better, the dependency is now really obvious, but also,
we no longer care in which order gdbpy_initialize_record and
gdbpy_initialize_instruction are called.

There should be no user visible changes after this commit.
---
 gdb/python/py-instruction.c | 41 +++++++++++++++++++++++++++++--------
 gdb/python/py-instruction.h | 13 ++++++++----
 gdb/python/py-record.c      |  2 +-
 3 files changed, 42 insertions(+), 14 deletions(-)

diff --git a/gdb/python/py-instruction.c b/gdb/python/py-instruction.c
index e1ad49a5143..fee5bba4015 100644
--- a/gdb/python/py-instruction.c
+++ b/gdb/python/py-instruction.c
@@ -20,7 +20,9 @@
 #include "defs.h"
 #include "py-instruction.h"
 
-/* See py-instruction.h.  */
+/* Python type object for the abstract gdb.Instruction class.  This class
+   contains getters for four elements: "pc" (int), "data" (buffer), "decode"
+   (str) and "size" (int) that must be overridden by sub classes.  */
 
 PyTypeObject py_insn_type = {
   PyVarObject_HEAD_INIT (NULL, 0)
@@ -51,17 +53,38 @@ static gdb_PyGetSetDef py_insn_getset[] =
   {NULL}
 };
 
+/* See py-instruction.h.  */
+
+PyTypeObject *
+py_insn_get_insn_type ()
+{
+  if (py_insn_type.tp_new == nullptr)
+    {
+      py_insn_type.tp_new = PyType_GenericNew;
+      py_insn_type.tp_flags = Py_TPFLAGS_DEFAULT;
+      py_insn_type.tp_basicsize = sizeof (py_insn_obj);
+      py_insn_type.tp_name = "gdb.Instruction";
+      py_insn_type.tp_doc = "GDB instruction object";
+      py_insn_type.tp_getset = py_insn_getset;
+
+      if (PyType_Ready (&py_insn_type) < 0)
+	{
+	  /* Reset the tp_new field so any subsequent calls to this
+	     function will retry to make the type ready.  */
+	  py_insn_type.tp_new = nullptr;
+	  return nullptr;
+	}
+    }
+
+  return &py_insn_type;
+}
+
 /* Sets up the gdb.Instruction type.  */
 
 int
 gdbpy_initialize_instruction (void)
 {
-  py_insn_type.tp_new = PyType_GenericNew;
-  py_insn_type.tp_flags = Py_TPFLAGS_DEFAULT;
-  py_insn_type.tp_basicsize = sizeof (py_insn_obj);
-  py_insn_type.tp_name = "gdb.Instruction";
-  py_insn_type.tp_doc = "GDB instruction object";
-  py_insn_type.tp_getset = py_insn_getset;
-
-  return PyType_Ready (&py_insn_type);
+  if (py_insn_get_insn_type () == nullptr)
+    return -1;
+  return 0;
 }
diff --git a/gdb/python/py-instruction.h b/gdb/python/py-instruction.h
index 59f0893e641..1e602636a39 100644
--- a/gdb/python/py-instruction.h
+++ b/gdb/python/py-instruction.h
@@ -22,9 +22,14 @@
 
 #include "python-internal.h"
 
-/* Python type object for the abstract gdb.Instruction class.  This class
-   contains getters for four elements: "pc" (int), "data" (buffer), "decode"
-   (str) and "size" (int) that must be overridden by sub classes.  */
-extern PyTypeObject py_insn_type;
+/* Return a pointer to the py_insn_type object (see py-instruction.c), but
+   ensure that PyType_Ready has been called for the type first.  If the
+   PyType_Ready call is successful then subsequent calls to this function
+   will not call PyType_Ready, the type pointer will just be returned.
+
+   If the PyType_Ready call is not successful then nullptr is returned and
+   subsequent calls to this function will call PyType_Ready again.  */
+
+extern PyTypeObject *py_insn_get_insn_type ();
 
 #endif /* PYTHON_PY_INSTRUCTION_H */
diff --git a/gdb/python/py-record.c b/gdb/python/py-record.c
index 51084dfac72..fd5cfee84eb 100644
--- a/gdb/python/py-record.c
+++ b/gdb/python/py-record.c
@@ -563,7 +563,7 @@ gdbpy_initialize_record (void)
   recpy_insn_type.tp_getset = recpy_insn_getset;
   recpy_insn_type.tp_richcompare = recpy_element_richcompare;
   recpy_insn_type.tp_hash = recpy_element_hash;
-  recpy_insn_type.tp_base = &py_insn_type;
+  recpy_insn_type.tp_base = py_insn_get_insn_type ();
 
   recpy_func_type.tp_new = PyType_GenericNew;
   recpy_func_type.tp_flags = Py_TPFLAGS_DEFAULT;
-- 
2.25.4


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 2/3] gdb/python: break more dependencies between gdbpy_initialize_* functions
  2022-10-02 16:53 [PATCH 0/3] New mechanism to initialise Python components in GDB Andrew Burgess
  2022-10-02 16:53 ` [PATCH 1/3] gdb/python: break dependencies between gdbpy_initialize_* functions Andrew Burgess
@ 2022-10-02 16:53 ` Andrew Burgess
  2022-10-14 17:06   ` Tom Tromey
  2022-10-02 16:53 ` [PATCH 3/3] gdb/python: add gdbpy_register_subsystem mechanism Andrew Burgess
  2 siblings, 1 reply; 13+ messages in thread
From: Andrew Burgess @ 2022-10-02 16:53 UTC (permalink / raw)
  To: gdb-patches

In a later commit in this series I will propose removing all of the
explicit gdbpy_initialize_* calls from python.c and replace these
calls with a more generic mechanism.

One of the side effects of this generic mechanism is that the order in
which the various Python sub-systems within GDB are initialized is no
longer guaranteed.

On the whole I don't think this matters, most of the sub-systems are
independent of each other, though testing did reveal a few places
where we did have dependencies, though I don't think those
dependencies were explicitly documented in comment anywhere.

This commit is similar to the previous one, and fixes the second
dependency issue that I found.

In this case the finish_breakpoint_object_type uses the
breakpoint_object_type as its tp_base, this means that
breakpoint_object_type must have been initialized with a call to
PyType_Ready before finish_breakpoint_object_type can be initialized.

Previously we depended on the ordering of calls to
gdbpy_initialize_breakpoints and gdbpy_initialize_finishbreakpoints in
python.c.

After this commit a new function gdbpy_breakpoint_init_breakpoint_type
exists, this function ensures that breakpoint_object_type has been
initialized, and can be called from any gdbpy_initialize_* function.

I feel that this change makes the dependency explicit, which I think
is a good thing.

There should be no user visible changes after this commit.
---
 gdb/python/py-breakpoint.c       | 23 +++++++++++++++++++++--
 gdb/python/py-finishbreakpoint.c |  3 +++
 gdb/python/python-internal.h     | 12 ++++++++++++
 3 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index dd4519a1b05..7a757432948 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -989,6 +989,26 @@ build_bp_list (struct breakpoint *b, PyObject *list)
   return PyList_Append (list, bp) == 0;
 }
 
+/* See python-internal.h.  */
+
+bool
+gdbpy_breakpoint_init_breakpoint_type ()
+{
+  if (breakpoint_object_type.tp_new == nullptr)
+    {
+      breakpoint_object_type.tp_new = PyType_GenericNew;
+      if (PyType_Ready (&breakpoint_object_type) < 0)
+	{
+	  /* Reset tp_new back to nullptr so future calls to this function
+	     will try calling PyType_Ready again.  */
+	  breakpoint_object_type.tp_new = nullptr;
+	  return false;
+	}
+    }
+
+  return true;
+}
+
 /* Static function to return a tuple holding all breakpoints.  */
 
 PyObject *
@@ -1216,8 +1236,7 @@ gdbpy_initialize_breakpoints (void)
 {
   int i;
 
-  breakpoint_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&breakpoint_object_type) < 0)
+  if (!gdbpy_breakpoint_init_breakpoint_type ())
     return -1;
 
   if (gdb_pymodule_addobject (gdb_module, "Breakpoint",
diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c
index c4b043f5bfe..67637f16a39 100644
--- a/gdb/python/py-finishbreakpoint.c
+++ b/gdb/python/py-finishbreakpoint.c
@@ -408,6 +408,9 @@ bpfinishpy_handle_exit (struct inferior *inf)
 int
 gdbpy_initialize_finishbreakpoints (void)
 {
+  if (!gdbpy_breakpoint_init_breakpoint_type ())
+    return -1;
+
   if (PyType_Ready (&finish_breakpoint_object_type) < 0)
     return -1;
 
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index d624b23fdc5..a4f54e78268 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -290,6 +290,18 @@ extern PyTypeObject frame_object_type
 extern PyTypeObject thread_object_type
     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("thread_object");
 
+/* Ensure that breakpoint_object_type is initialized and return true.  If
+   breakpoint_object_type can't be initialized then set a suitable Python
+   error and return false.
+
+   This function needs to be called from any gdbpy_initialize_* function
+   that wants to reference breakpoint_object_type.  After all the
+   gdbpy_initialize_* functions have been called then breakpoint_object_type
+   is guaranteed to have been initialized, and this function does not need
+   calling before referencing breakpoint_object_type.  */
+
+extern bool gdbpy_breakpoint_init_breakpoint_type ();
+
 struct gdbpy_breakpoint_object
 {
   PyObject_HEAD
-- 
2.25.4


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 3/3] gdb/python: add gdbpy_register_subsystem mechanism
  2022-10-02 16:53 [PATCH 0/3] New mechanism to initialise Python components in GDB Andrew Burgess
  2022-10-02 16:53 ` [PATCH 1/3] gdb/python: break dependencies between gdbpy_initialize_* functions Andrew Burgess
  2022-10-02 16:53 ` [PATCH 2/3] gdb/python: break more " Andrew Burgess
@ 2022-10-02 16:53 ` Andrew Burgess
  2022-10-14 17:20   ` Tom Tromey
  2 siblings, 1 reply; 13+ messages in thread
From: Andrew Burgess @ 2022-10-02 16:53 UTC (permalink / raw)
  To: gdb-patches

Currently, when we add a new python sub-system to GDB,
e.g. py-inferior.c, we end up having to create a new function like
gdbpy_initialize_inferior, which then has to be called from the
function do_start_initialization in python.c.

In some cases (or currently just the one case), like py-micmd.c, we
have two functions gdbpy_initialize_micommands, and
gdbpy_finalize_micommands, with the second being called from
finalize_python which is also in python.c.

This commit proposes a mechanism to manage these initialization and
finalization calls, this means that adding a new Python subsystem will
no longer require changes to python.c, instead, the initialization and
finalization functions will be registered directly from the sub-system
file, e.g. py-inferior.c, or py-micmd.c.

A new function gdbpy_register_subsystem will be added which takes two
callbacks, the first is an initialization callback,
e.g. gdbpy_initialize_micommands, and the second is a finalization
callback, e.g. gdbpy_finalize_micommands.  The second callback is
optional, and defaults to nullptr.

All callbacks registered through gdbpy_register_subsystem are added to
a vector, and in python.c we iterate over the vector and all the
various functions as needed.

The only question is when should gdbpy_register_subsystem be called?
The answer I think is to make use of GDB's existing _initialize_*
function mechanism.  A few of the python sub-system files already
include an _initialize_* function, but most needed to have one added.

One possible problem with this change is that there is now no
guaranteed ordering of how the various sub-systems are initialized (or
finalized).  The previous two commits have removed all the implicit
dependencies that existed between sub-systems, and replaced them with
more explicit dependencies.  With those two commits in place I now
believe that there are no dependencies on the order in which the
gdbpy_initialize_* functions are called.

To satisfy myself that this was true I ran the testsuite with the
patch as presented here, but also, I modified GDB so that the
gdbpy_initialize_* functions were called in reverse order, and ran the
testsuite again.  I saw no regressions in either case.

As there's only a single finalize call right now then we can be sure
that there's no dependencies there.

One other change of note was for gdbpy_initialize_gdb_readline, this
function previously returned void.  In order to make this function
have the correct signature I've updated its return type to int, and we
now return 0 to indicate success.

All of the other initialize (and finalize) functions have been made
static within their respective sub-system files.

There should be no user visible changes after this commit.
---
 gdb/python/py-arch.c             |  11 +++-
 gdb/python/py-auto-load.c        |   9 ++-
 gdb/python/py-block.c            |   9 ++-
 gdb/python/py-breakpoint.c       |   7 ++-
 gdb/python/py-cmd.c              |   9 ++-
 gdb/python/py-connection.c       |   4 +-
 gdb/python/py-disasm.c           |  11 +++-
 gdb/python/py-event.c            |   9 ++-
 gdb/python/py-evtregistry.c      |   9 ++-
 gdb/python/py-finishbreakpoint.c |  11 +++-
 gdb/python/py-frame.c            |   9 ++-
 gdb/python/py-function.c         |   9 ++-
 gdb/python/py-gdb-readline.c     |  10 ++-
 gdb/python/py-inferior.c         |  11 +++-
 gdb/python/py-infthread.c        |  11 +++-
 gdb/python/py-instruction.c      |   9 ++-
 gdb/python/py-lazy-string.c      |   9 ++-
 gdb/python/py-linetable.c        |   9 ++-
 gdb/python/py-membuf.c           |  11 +++-
 gdb/python/py-micmd.c            |   9 ++-
 gdb/python/py-objfile.c          |   9 ++-
 gdb/python/py-param.c            |   9 ++-
 gdb/python/py-progspace.c        |   9 ++-
 gdb/python/py-record-btrace.c    |   9 ++-
 gdb/python/py-record.c           |   9 ++-
 gdb/python/py-registers.c        |  11 +++-
 gdb/python/py-symbol.c           |   9 ++-
 gdb/python/py-symtab.c           |   9 ++-
 gdb/python/py-tui.c              |   9 ++-
 gdb/python/py-type.c             |   9 ++-
 gdb/python/py-unwind.c           |  34 ++++++-----
 gdb/python/py-value.c            |   9 ++-
 gdb/python/py-xmethods.c         |   9 ++-
 gdb/python/python-internal.h     | 102 ++++++++++---------------------
 gdb/python/python.c              |  73 +++++++++++-----------
 35 files changed, 349 insertions(+), 156 deletions(-)

diff --git a/gdb/python/py-arch.c b/gdb/python/py-arch.c
index cf0978560f9..bd172d6f8c8 100644
--- a/gdb/python/py-arch.c
+++ b/gdb/python/py-arch.c
@@ -344,7 +344,7 @@ gdbpy_all_architecture_names (PyObject *self, PyObject *args)
 
 /* Initializes the Architecture class in the gdb module.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_arch (void)
 {
   arch_object_type.tp_new = PyType_GenericNew;
@@ -355,6 +355,15 @@ gdbpy_initialize_arch (void)
 				 (PyObject *) &arch_object_type);
 }
 
+void _initialize_py_arch ();
+void
+_initialize_py_arch ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_arch);
+}
+
+\f
+
 static PyMethodDef arch_object_methods [] = {
   { "name", archpy_name, METH_NOARGS,
     "name () -> String.\n\
diff --git a/gdb/python/py-auto-load.c b/gdb/python/py-auto-load.c
index 5d60460683a..50131806c18 100644
--- a/gdb/python/py-auto-load.c
+++ b/gdb/python/py-auto-load.c
@@ -56,7 +56,7 @@ info_auto_load_python_scripts (const char *pattern, int from_tty)
   auto_load_info_scripts (pattern, from_tty, &extension_language_python);
 }
 \f
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_auto_load (void)
 {
   add_setshow_boolean_cmd ("python-scripts", class_support,
@@ -95,3 +95,10 @@ Print the list of automatically loaded Python scripts, deprecated."));
 
   return 0;
 }
+
+void _initialize_py_auto_load ();
+void
+_initialize_py_auto_load ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_auto_load);
+}
diff --git a/gdb/python/py-block.c b/gdb/python/py-block.c
index b9aea3aca69..204571192bd 100644
--- a/gdb/python/py-block.c
+++ b/gdb/python/py-block.c
@@ -424,7 +424,7 @@ blpy_iter_is_valid (PyObject *self, PyObject *args)
   Py_RETURN_TRUE;
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_blocks (void)
 {
   block_object_type.tp_new = PyType_GenericNew;
@@ -443,6 +443,13 @@ gdbpy_initialize_blocks (void)
 				 (PyObject *) &block_syms_iterator_object_type);
 }
 
+void _initialize_py_block ();
+void
+_initialize_py_block ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_blocks);
+}
+
 \f
 
 static PyMethodDef block_object_methods[] = {
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index 7a757432948..8c972761bf9 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -1231,7 +1231,7 @@ gdbpy_breakpoint_modified (struct breakpoint *b)
 \f
 
 /* Initialize the Python breakpoint code.  */
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_breakpoints (void)
 {
   int i;
@@ -1271,7 +1271,7 @@ gdbpy_initialize_breakpoints (void)
 
 /* Initialize the Python BreakpointLocation code.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_breakpoint_locations ()
 {
   if (PyType_Ready (&breakpoint_location_object_type) < 0)
@@ -1433,6 +1433,9 @@ _initialize_py_breakpoint ()
 	NULL,
 	show_pybp_debug,
 	&setdebuglist, &showdebuglist);
+
+  gdbpy_register_subsystem (gdbpy_initialize_breakpoints);
+  gdbpy_register_subsystem (gdbpy_initialize_breakpoint_locations);
 }
 
 /* Python function to set the enabled state of a breakpoint location.  */
diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c
index 5cc392af175..e32686da63e 100644
--- a/gdb/python/py-cmd.c
+++ b/gdb/python/py-cmd.c
@@ -551,7 +551,7 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
 
 /* Initialize the 'commands' code.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_commands (void)
 {
   int i;
@@ -601,6 +601,13 @@ gdbpy_initialize_commands (void)
   return 0;
 }
 
+void _initialize_py_cmd ();
+void
+_initialize_py_cmd ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_commands);
+}
+
 \f
 
 static PyMethodDef cmdpy_object_methods[] =
diff --git a/gdb/python/py-connection.c b/gdb/python/py-connection.c
index 84660414dd0..d9ffe0d314c 100644
--- a/gdb/python/py-connection.c
+++ b/gdb/python/py-connection.c
@@ -285,7 +285,7 @@ connpy_get_connection_details (PyObject *self, void *closure)
 
 /* Python specific initialization for this file.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_connection (void)
 {
   if (PyType_Ready (&connection_object_type) < 0)
@@ -445,6 +445,8 @@ _initialize_py_connection ()
 {
   gdb::observers::connection_removed.attach (connpy_connection_removed,
 					     "py-connection");
+
+  gdbpy_register_subsystem (gdbpy_initialize_connection);
 }
 
 /* Methods for the gdb.TargetConnection object type.  */
diff --git a/gdb/python/py-disasm.c b/gdb/python/py-disasm.c
index c37452fcf72..118b50ee208 100644
--- a/gdb/python/py-disasm.c
+++ b/gdb/python/py-disasm.c
@@ -971,7 +971,7 @@ static struct PyModuleDef python_disassembler_module_def =
 
 /* Called to initialize the Python structures in this file.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_disasm ()
 {
   /* Create the _gdb.disassembler module, and add it to the _gdb module.  */
@@ -1005,6 +1005,15 @@ gdbpy_initialize_disasm ()
   return 0;
 }
 
+void _initialize_py_disasm ();
+void
+_initialize_py_disasm ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_disasm);
+}
+
+\f
+
 /* Describe the gdb.disassembler.DisassembleInfo type.  */
 
 PyTypeObject disasm_info_object_type = {
diff --git a/gdb/python/py-event.c b/gdb/python/py-event.c
index 4d8a0b909c0..a540243aa6d 100644
--- a/gdb/python/py-event.c
+++ b/gdb/python/py-event.c
@@ -54,7 +54,7 @@ evpy_add_attribute (PyObject *event, const char *name, PyObject *attr)
 
 /* Initialize the Python event code.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_event (void)
 {
   return gdbpy_initialize_event_generic (&event_object_type,
@@ -114,6 +114,13 @@ evpy_emit_event (PyObject *event,
   return 0;
 }
 
+void _initialize_py_event ();
+void
+_initialize_py_event ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_event);
+}
+
 static gdb_PyGetSetDef event_object_getset[] =
 {
   { "__dict__", gdb_py_generic_dict, NULL,
diff --git a/gdb/python/py-evtregistry.c b/gdb/python/py-evtregistry.c
index f3a7f0ca244..9d83c54120c 100644
--- a/gdb/python/py-evtregistry.c
+++ b/gdb/python/py-evtregistry.c
@@ -102,7 +102,7 @@ evregpy_dealloc (PyObject *self)
 
 /* Initialize the Python event registry code.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_eventregistry (void)
 {
   if (PyType_Ready (&eventregistry_object_type) < 0)
@@ -123,6 +123,13 @@ evregpy_no_listeners_p (eventregistry_object *registry)
   return registry == nullptr || PyList_Size (registry->callbacks) == 0;
 }
 
+void _initialize_py_evtregistry ();
+void
+_initialize_py_evtregistry ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_eventregistry);
+}
+
 static PyMethodDef eventregistry_object_methods[] =
 {
   { "connect", evregpy_connect, METH_VARARGS, "Add function" },
diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c
index 67637f16a39..46b188c7a93 100644
--- a/gdb/python/py-finishbreakpoint.c
+++ b/gdb/python/py-finishbreakpoint.c
@@ -405,7 +405,7 @@ bpfinishpy_handle_exit (struct inferior *inf)
 
 /* Initialize the Python finish breakpoint code.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_finishbreakpoints (void)
 {
   if (!gdbpy_breakpoint_init_breakpoint_type ())
@@ -426,6 +426,15 @@ gdbpy_initialize_finishbreakpoints (void)
   return 0;
 }
 
+void _initialize_py_finishbreakpoint ();
+void
+_initialize_py_finishbreakpoint ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_finishbreakpoints);
+}
+
+\f
+
 static gdb_PyGetSetDef finish_breakpoint_object_getset[] = {
   { "return_value", bpfinishpy_get_returnvalue, NULL,
   "gdb.Value object representing the return value, if any. \
diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c
index 8bd2e0bc6da..af7a5e88c75 100644
--- a/gdb/python/py-frame.c
+++ b/gdb/python/py-frame.c
@@ -713,7 +713,7 @@ frapy_richcompare (PyObject *self, PyObject *other, int op)
 
 /* Sets up the Frame API in the gdb module.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_frames (void)
 {
   frame_object_type.tp_new = PyType_GenericNew;
@@ -745,6 +745,13 @@ gdbpy_initialize_frames (void)
 				 (PyObject *) &frame_object_type);
 }
 
+void _initialize_py_frame ();
+void
+_initialize_py_frame ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_frames);
+}
+
 \f
 
 static PyMethodDef frame_object_methods[] = {
diff --git a/gdb/python/py-function.c b/gdb/python/py-function.c
index c314ee5da71..45e72f3d289 100644
--- a/gdb/python/py-function.c
+++ b/gdb/python/py-function.c
@@ -134,7 +134,7 @@ fnpy_init (PyObject *self, PyObject *args, PyObject *kwds)
 
 /* Initialize internal function support.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_functions (void)
 {
   fnpy_object_type.tp_new = PyType_GenericNew;
@@ -145,6 +145,13 @@ gdbpy_initialize_functions (void)
 				 (PyObject *) &fnpy_object_type);
 }
 
+void _initialize_py_function ();
+void
+_initialize_py_function ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_functions);
+}
+
 \f
 
 PyTypeObject fnpy_object_type =
diff --git a/gdb/python/py-gdb-readline.c b/gdb/python/py-gdb-readline.c
index af388d5ed72..c7c38eea89d 100644
--- a/gdb/python/py-gdb-readline.c
+++ b/gdb/python/py-gdb-readline.c
@@ -85,7 +85,7 @@ gdbpy_readline_wrapper (FILE *sys_stdin, FILE *sys_stdout,
 
 /* Initialize Python readline support.  */
 
-void
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_gdb_readline (void)
 {
   /* Python's readline module conflicts with GDB's use of readline
@@ -109,5 +109,13 @@ class GdbRemoveReadlineFinder:\n\
 sys.meta_path.append(GdbRemoveReadlineFinder())\n\
 ") == 0)
     PyOS_ReadlineFunctionPointer = gdbpy_readline_wrapper;
+
+  return 0;
 }
 
+void _initialize_py_gdb_readline ();
+void
+_initialize_py_gdb_readline ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_gdb_readline);
+}
diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c
index 0066ae6d6a9..b2c4a11086f 100644
--- a/gdb/python/py-inferior.c
+++ b/gdb/python/py-inferior.c
@@ -833,7 +833,7 @@ gdbpy_selected_inferior (PyObject *self, PyObject *args)
 	  inferior_to_inferior_object (current_inferior ()).release ());
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_inferior (void)
 {
   if (PyType_Ready (&inferior_object_type) < 0)
@@ -869,6 +869,15 @@ gdbpy_initialize_inferior (void)
   return 0;
 }
 
+void _initialize_py_inferior ();
+void
+_initialize_py_inferior ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_inferior);
+}
+
+\f
+
 static gdb_PyGetSetDef inferior_object_getset[] =
 {
   { "num", infpy_get_num, NULL, "ID of inferior, as assigned by GDB.", NULL },
diff --git a/gdb/python/py-infthread.c b/gdb/python/py-infthread.c
index 34f60526ac9..1e474299f77 100644
--- a/gdb/python/py-infthread.c
+++ b/gdb/python/py-infthread.c
@@ -361,7 +361,7 @@ gdbpy_selected_thread (PyObject *self, PyObject *args)
   Py_RETURN_NONE;
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_thread (void)
 {
   if (PyType_Ready (&thread_object_type) < 0)
@@ -371,6 +371,15 @@ gdbpy_initialize_thread (void)
 				 (PyObject *) &thread_object_type);
 }
 
+void _initialize_py_infthread ();
+void
+_initialize_py_infthread ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_thread);
+}
+
+\f
+
 static gdb_PyGetSetDef thread_object_getset[] =
 {
   { "name", thpy_get_name, thpy_set_name,
diff --git a/gdb/python/py-instruction.c b/gdb/python/py-instruction.c
index fee5bba4015..3fe39411507 100644
--- a/gdb/python/py-instruction.c
+++ b/gdb/python/py-instruction.c
@@ -81,10 +81,17 @@ py_insn_get_insn_type ()
 
 /* Sets up the gdb.Instruction type.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_instruction (void)
 {
   if (py_insn_get_insn_type () == nullptr)
     return -1;
   return 0;
 }
+
+void _initialize_py_instruction ();
+void
+_initialize_py_instruction ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_instruction);
+}
diff --git a/gdb/python/py-lazy-string.c b/gdb/python/py-lazy-string.c
index 8cd8b91e91b..5f8afcef858 100644
--- a/gdb/python/py-lazy-string.c
+++ b/gdb/python/py-lazy-string.c
@@ -229,7 +229,7 @@ gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
   return (PyObject *) str_obj;
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_lazy_string (void)
 {
   if (PyType_Ready (&lazy_string_object_type) < 0)
@@ -291,6 +291,13 @@ gdbpy_extract_lazy_string (PyObject *string, CORE_ADDR *addr,
   encoding->reset (lazy->encoding ? xstrdup (lazy->encoding) : NULL);
 }
 
+void _initialize_py_lazy_string ();
+void
+_initialize_py_lazy_string ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_lazy_string);
+}
+
 \f
 
 static PyMethodDef lazy_string_object_methods[] = {
diff --git a/gdb/python/py-linetable.c b/gdb/python/py-linetable.c
index 8e545febb17..53cc3c23d22 100644
--- a/gdb/python/py-linetable.c
+++ b/gdb/python/py-linetable.c
@@ -286,7 +286,7 @@ ltpy_dealloc (PyObject *self)
 /* Initialize LineTable, LineTableEntry and LineTableIterator
    objects.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_linetable (void)
 {
   if (PyType_Ready (&linetable_object_type) < 0)
@@ -446,6 +446,13 @@ ltpy_iter_is_valid (PyObject *self, PyObject *args)
   Py_RETURN_TRUE;
 }
 
+void _initialize_py_linetable ();
+void
+_initialize_py_linetable ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_linetable);
+}
+
 \f
 
 static PyMethodDef linetable_object_methods[] = {
diff --git a/gdb/python/py-membuf.c b/gdb/python/py-membuf.c
index d2a059a0e34..d4b830b7a40 100644
--- a/gdb/python/py-membuf.c
+++ b/gdb/python/py-membuf.c
@@ -99,7 +99,7 @@ get_buffer (PyObject *self, Py_buffer *buf, int flags)
 
 /* General Python initialization callback.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_membuf (void)
 {
   membuf_object_type.tp_new = PyType_GenericNew;
@@ -110,6 +110,15 @@ gdbpy_initialize_membuf (void)
 				 (PyObject *) &membuf_object_type);
 }
 
+void _initialize_py_membuf ();
+void
+_initialize_py_membuf ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_membuf);
+}
+
+\f
+
 static PyBufferProcs buffer_procs =
 {
   get_buffer
diff --git a/gdb/python/py-micmd.c b/gdb/python/py-micmd.c
index 79e2575f789..b72d66d8154 100644
--- a/gdb/python/py-micmd.c
+++ b/gdb/python/py-micmd.c
@@ -595,7 +595,7 @@ micmdpy_dealloc (PyObject *obj)
 
 /* Python initialization for the MI commands components.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_micommands ()
 {
   micmdpy_object_type.tp_new = PyType_GenericNew;
@@ -614,7 +614,9 @@ gdbpy_initialize_micommands ()
   return 0;
 }
 
-void
+/* Cleanup just before GDB shuts down the Python interpreter.  */
+
+static void
 gdbpy_finalize_micommands ()
 {
   /* mi_command_py objects hold references to micmdpy_object objects.  They must
@@ -736,4 +738,7 @@ _initialize_py_micmd ()
      nullptr,
      show_pymicmd_debug,
      &setdebuglist, &showdebuglist);
+
+  gdbpy_register_subsystem (gdbpy_initialize_micommands,
+			    gdbpy_finalize_micommands);
 }
diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
index 757f9aac4fc..e2bcefb58c5 100644
--- a/gdb/python/py-objfile.c
+++ b/gdb/python/py-objfile.c
@@ -708,7 +708,7 @@ objfile_to_objfile_object (struct objfile *objfile)
   return gdbpy_ref<>::new_reference (result);
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_objfile (void)
 {
   if (PyType_Ready (&objfile_object_type) < 0)
@@ -718,6 +718,13 @@ gdbpy_initialize_objfile (void)
 				 (PyObject *) &objfile_object_type);
 }
 
+void _initialize_py_objfile ();
+void
+_initialize_py_objfile ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_objfile);
+}
+
 \f
 
 static PyMethodDef objfile_object_methods[] =
diff --git a/gdb/python/py-param.c b/gdb/python/py-param.c
index 5d509ba4658..17c6e365ea9 100644
--- a/gdb/python/py-param.c
+++ b/gdb/python/py-param.c
@@ -828,7 +828,7 @@ parmpy_dealloc (PyObject *obj)
 }
 
 /* Initialize the 'parameters' module.  */
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_parameters (void)
 {
   int i;
@@ -856,6 +856,13 @@ gdbpy_initialize_parameters (void)
 				 (PyObject *) &parmpy_object_type);
 }
 
+void _initialize_py_param ();
+void
+_initialize_py_param ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_parameters);
+}
+
 \f
 
 PyTypeObject parmpy_object_type =
diff --git a/gdb/python/py-progspace.c b/gdb/python/py-progspace.c
index 4eb33e8292f..18ea7c0ca60 100644
--- a/gdb/python/py-progspace.c
+++ b/gdb/python/py-progspace.c
@@ -529,7 +529,7 @@ gdbpy_is_progspace (PyObject *obj)
   return PyObject_TypeCheck (obj, &pspace_object_type);
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_pspace (void)
 {
   if (PyType_Ready (&pspace_object_type) < 0)
@@ -539,6 +539,13 @@ gdbpy_initialize_pspace (void)
 				 (PyObject *) &pspace_object_type);
 }
 
+void _initialize_py_progspace ();
+void
+_initialize_py_progspace ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_pspace);
+}
+
 \f
 
 static gdb_PyGetSetDef pspace_getset[] =
diff --git a/gdb/python/py-record-btrace.c b/gdb/python/py-record-btrace.c
index 85401010f0a..4a7dc09a45d 100644
--- a/gdb/python/py-record-btrace.c
+++ b/gdb/python/py-record-btrace.c
@@ -816,7 +816,7 @@ static PyMappingMethods btpy_list_mapping_methods =
 
 /* Sets up the btrace record API.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_btrace (void)
 {
   btpy_list_type.tp_new = PyType_GenericNew;
@@ -837,3 +837,10 @@ gdbpy_initialize_btrace (void)
 
   return PyType_Ready (&btpy_list_type);
 }
+
+void _initialize_py_record_btrace ();
+void
+_initialize_py_record_btrace ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_btrace);
+}
diff --git a/gdb/python/py-record.c b/gdb/python/py-record.c
index fd5cfee84eb..04f5fc802b3 100644
--- a/gdb/python/py-record.c
+++ b/gdb/python/py-record.c
@@ -544,7 +544,7 @@ static gdb_PyGetSetDef recpy_gap_getset[] = {
 
 /* Sets up the record API in the gdb module.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_record (void)
 {
   recpy_record_type.tp_new = PyType_GenericNew;
@@ -648,3 +648,10 @@ gdbpy_stop_recording (PyObject *self, PyObject *args)
 
   Py_RETURN_NONE;
 }
+
+void _initialize_py_record ();
+void
+_initialize_py_record ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_record);
+}
diff --git a/gdb/python/py-registers.c b/gdb/python/py-registers.c
index fe7481cea9e..542317d3970 100644
--- a/gdb/python/py-registers.c
+++ b/gdb/python/py-registers.c
@@ -427,7 +427,7 @@ gdbpy_parse_register_id (struct gdbarch *gdbarch, PyObject *pyo_reg_id,
 
 /* Initializes the new Python classes from this file in the gdb module.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_registers ()
 {
   register_descriptor_object_type.tp_new = PyType_GenericNew;
@@ -462,6 +462,15 @@ gdbpy_initialize_registers ()
 	   (PyObject *) &register_descriptor_iterator_object_type));
 }
 
+void _initialize_py_registers ();
+void
+_initialize_py_registers ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_registers);
+}
+
+\f
+
 static PyMethodDef register_descriptor_iterator_object_methods [] = {
   { "find", (PyCFunction) register_descriptor_iter_find,
     METH_VARARGS | METH_KEYWORDS,
diff --git a/gdb/python/py-symbol.c b/gdb/python/py-symbol.c
index e5fe5cf8c92..e1d7eca7f58 100644
--- a/gdb/python/py-symbol.c
+++ b/gdb/python/py-symbol.c
@@ -611,7 +611,7 @@ gdbpy_lookup_static_symbols (PyObject *self, PyObject *args, PyObject *kw)
   return return_list.release ();
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_symbols (void)
 {
   if (PyType_Ready (&symbol_object_type) < 0)
@@ -680,6 +680,13 @@ gdbpy_initialize_symbols (void)
 				 (PyObject *) &symbol_object_type);
 }
 
+void _initialize_py_symbol ();
+void
+_initialize_py_symbol ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_symbols);
+}
+
 \f
 
 static gdb_PyGetSetDef symbol_object_getset[] = {
diff --git a/gdb/python/py-symtab.c b/gdb/python/py-symtab.c
index 03c274dfff6..826ffc19e13 100644
--- a/gdb/python/py-symtab.c
+++ b/gdb/python/py-symtab.c
@@ -509,7 +509,7 @@ symtab_object_to_symtab (PyObject *obj)
   return ((symtab_object *) obj)->symtab;
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_symtabs (void)
 {
   symtab_object_type.tp_new = PyType_GenericNew;
@@ -528,6 +528,13 @@ gdbpy_initialize_symtabs (void)
 				 (PyObject *) &sal_object_type);
 }
 
+void _initialize_py_symtab ();
+void
+_initialize_py_symtab ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_symtabs);
+}
+
 \f
 
 static gdb_PyGetSetDef symtab_object_getset[] = {
diff --git a/gdb/python/py-tui.c b/gdb/python/py-tui.c
index 6a92251a705..b69fbf1f3c1 100644
--- a/gdb/python/py-tui.c
+++ b/gdb/python/py-tui.c
@@ -561,7 +561,7 @@ PyTypeObject gdbpy_tui_window_object_type =
 
 /* Initialize this module.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_tui ()
 {
 #ifdef TUI
@@ -572,3 +572,10 @@ gdbpy_initialize_tui ()
 
   return 0;
 }
+
+void _initialize_py_tui ();
+void
+_initialize_py_tui ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_tui);
+}
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index 3e558dee7ad..cf18470ba58 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -1465,7 +1465,7 @@ gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw)
   return type_to_type_object (type);
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_types (void)
 {
   if (PyType_Ready (&type_object_type) < 0)
@@ -1493,6 +1493,13 @@ gdbpy_initialize_types (void)
 				 (PyObject *) &field_object_type);
 }
 
+void _initialize_py_type ();
+void
+_initialize_py_type ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_types);
+}
+
 \f
 
 static gdb_PyGetSetDef type_object_getset[] =
diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
index 0a1b460e785..c0a35fda6f9 100644
--- a/gdb/python/py-unwind.c
+++ b/gdb/python/py-unwind.c
@@ -682,23 +682,9 @@ pyuw_on_new_gdbarch (struct gdbarch *newarch)
     }
 }
 
-void _initialize_py_unwind ();
-void
-_initialize_py_unwind ()
-{
-  add_setshow_boolean_cmd
-      ("py-unwind", class_maintenance, &pyuw_debug,
-	_("Set Python unwinder debugging."),
-	_("Show Python unwinder debugging."),
-	_("When on, Python unwinder debugging is enabled."),
-	NULL,
-	show_pyuw_debug,
-	&setdebuglist, &showdebuglist);
-}
-
 /* Initialize unwind machinery.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_unwind (void)
 {
   gdb::observers::architecture_changed.attach (pyuw_on_new_gdbarch,
@@ -717,6 +703,24 @@ gdbpy_initialize_unwind (void)
       (PyObject *) &unwind_info_object_type);
 }
 
+void _initialize_py_unwind ();
+void
+_initialize_py_unwind ()
+{
+  add_setshow_boolean_cmd
+      ("py-unwind", class_maintenance, &pyuw_debug,
+	_("Set Python unwinder debugging."),
+	_("Show Python unwinder debugging."),
+	_("When on, Python unwinder debugging is enabled."),
+	NULL,
+	show_pyuw_debug,
+	&setdebuglist, &showdebuglist);
+
+  gdbpy_register_subsystem (gdbpy_initialize_unwind);
+}
+
+\f
+
 static PyMethodDef pending_frame_object_methods[] =
 {
   { "read_register", pending_framepy_read_register, METH_VARARGS,
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index 92a15304c34..5ca8aa0f0f7 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -2059,7 +2059,7 @@ gdbpy_is_value_object (PyObject *obj)
   return PyObject_TypeCheck (obj, &value_object_type);
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_values (void)
 {
   if (PyType_Ready (&value_object_type) < 0)
@@ -2069,6 +2069,13 @@ gdbpy_initialize_values (void)
 				 (PyObject *) &value_object_type);
 }
 
+void _initialize_py_value ();
+void
+_initialize_py_value ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_values);
+}
+
 \f
 
 static gdb_PyGetSetDef value_object_getset[] = {
diff --git a/gdb/python/py-xmethods.c b/gdb/python/py-xmethods.c
index 1467e52a960..adee4893b46 100644
--- a/gdb/python/py-xmethods.c
+++ b/gdb/python/py-xmethods.c
@@ -598,7 +598,7 @@ python_xmethod_worker::python_xmethod_worker (PyObject *py_worker,
   Py_INCREF (this_type);
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_xmethods (void)
 {
   py_match_method_name = PyUnicode_FromString (match_method_name);
@@ -612,3 +612,10 @@ gdbpy_initialize_xmethods (void)
 
   return 1;
 }
+
+void _initialize_py_xmethods ();
+void
+_initialize_py_xmethods ()
+{
+  gdbpy_register_subsystem (gdbpy_initialize_xmethods);
+}
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index a4f54e78268..9630a0dab56 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -489,76 +489,38 @@ struct gdbarch *arch_object_to_gdbarch (PyObject *obj);
 
 extern struct program_space *progspace_object_to_program_space (PyObject *obj);
 
-void gdbpy_initialize_gdb_readline (void);
-int gdbpy_initialize_auto_load (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_values (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_frames (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_instruction (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_btrace (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_record (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_symtabs (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_commands (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_symbols (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_symtabs (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_blocks (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_types (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_functions (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_pspace (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_objfile (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_breakpoints (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_breakpoint_locations ()
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_finishbreakpoints (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_lazy_string (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_linetable (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_parameters (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_thread (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_inferior (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_eventregistry (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_event (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_arch (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_registers ()
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_xmethods (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_unwind (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_tui ()
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_membuf ()
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_connection ()
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_micommands (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-void gdbpy_finalize_micommands ();
-int gdbpy_initialize_disasm ()
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
+/* The type of a function that can be called just after GDB has setup the
+   Python interpreter.  This function will setup any additional Python
+   state required by a particular subsystem.  Return 0 if the setup was
+   successful, or return -1 if setup failed, in which case a Python
+   exception should have been raised.  */
+
+typedef int (*gdbpy_initialize_file_func_t) (void);
+
+/* The type of a function that can be called just before GDB shuts down
+   the Python interpreter.  This function can cleanup an Python state that
+   is cached within GDB, for example, if GDB is holding any references to
+   Python objects, these should be released before the Python interpreter
+   is shut down.
+
+   There is no error return in this case.  This function is only called
+   when GDB is already shutting down.  The function should make a best
+   effort to clean up, and then return.  */
+
+typedef void (*gdbpy_finalize_file_func_t) (void);
+
+/* Register the initialization (INIT) and finalization (FINI) functions for
+   a Python subsystem.  See the comments on the function types above for
+   when these functions will be called.
+
+   Either of these functions can be nullptr, in which case no function will
+   be called.
+
+   The FINI argument is optional, and defaults to nullptr (no function to
+   call).  */
+
+void gdbpy_register_subsystem (gdbpy_initialize_file_func_t init,
+			       gdbpy_finalize_file_func_t fini = nullptr);
 
 PyMODINIT_FUNC gdbpy_events_mod_func ();
 
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 516e2c983cf..afb4464aad7 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -196,6 +196,26 @@ const struct extension_language_defn extension_language_python =
 
 #ifdef HAVE_PYTHON
 
+/* A pair containing two function pointers.  The first pointer is to be
+   called just after GDB has setup the Python interpreter, and the second
+   is to be called just before GDB shuts down the Python interpreter.  */
+
+using callback_pair_t = std::pair<gdbpy_initialize_file_func_t,
+				  gdbpy_finalize_file_func_t>;
+
+/* A list of callback pairs.  */
+
+static std::vector<callback_pair_t> gdbpy_setup_callbacks;
+
+/* See python-internal.h.  */
+
+void
+gdbpy_register_subsystem (gdbpy_initialize_file_func_t init,
+			  gdbpy_finalize_file_func_t fini)
+{
+  gdbpy_setup_callbacks.emplace_back (init, fini);
+}
+
 /* Architecture and language to be used in callbacks from
    the Python interpreter.  */
 struct gdbarch *gdbpy_enter::python_gdbarch;
@@ -1934,7 +1954,14 @@ finalize_python (void *ignore)
   (void) PyGILState_Ensure ();
   gdbpy_enter::finalize ();
 
-  gdbpy_finalize_micommands ();
+  /* Every item in GDBPY_SETUP_CALLBACKS is a pair.  The second item in
+     the pair is (when not nullptr), a function to call to cleanup a
+     particular Python subsystem within GDB.  */
+  for (const auto &p : gdbpy_setup_callbacks)
+    {
+      if (p.second != nullptr)
+	p.second ();
+    }
 
   Py_Finalize ();
 
@@ -2122,42 +2149,14 @@ do_start_initialization ()
 				 gdbpy_gdberror_exc) < 0)
     return false;
 
-  gdbpy_initialize_gdb_readline ();
-
-  if (gdbpy_initialize_auto_load () < 0
-      || gdbpy_initialize_values () < 0
-      || gdbpy_initialize_disasm () < 0
-      || gdbpy_initialize_frames () < 0
-      || gdbpy_initialize_commands () < 0
-      || gdbpy_initialize_instruction () < 0
-      || gdbpy_initialize_record () < 0
-      || gdbpy_initialize_btrace () < 0
-      || gdbpy_initialize_symbols () < 0
-      || gdbpy_initialize_symtabs () < 0
-      || gdbpy_initialize_blocks () < 0
-      || gdbpy_initialize_functions () < 0
-      || gdbpy_initialize_parameters () < 0
-      || gdbpy_initialize_types () < 0
-      || gdbpy_initialize_pspace () < 0
-      || gdbpy_initialize_objfile () < 0
-      || gdbpy_initialize_breakpoints () < 0
-      || gdbpy_initialize_breakpoint_locations () < 0
-      || gdbpy_initialize_finishbreakpoints () < 0
-      || gdbpy_initialize_lazy_string () < 0
-      || gdbpy_initialize_linetable () < 0
-      || gdbpy_initialize_thread () < 0
-      || gdbpy_initialize_inferior () < 0
-      || gdbpy_initialize_eventregistry () < 0
-      || gdbpy_initialize_event () < 0
-      || gdbpy_initialize_arch () < 0
-      || gdbpy_initialize_registers () < 0
-      || gdbpy_initialize_xmethods () < 0
-      || gdbpy_initialize_unwind () < 0
-      || gdbpy_initialize_membuf () < 0
-      || gdbpy_initialize_connection () < 0
-      || gdbpy_initialize_tui () < 0
-      || gdbpy_initialize_micommands () < 0)
-    return false;
+  /* Every item in GDBPY_SETUP_CALLBACKS is a pair.  The first item in the
+     pair is (when not nullptr), a function to call to setup a particular
+     Python subsystem within GDB.  */
+  for (const auto &p : gdbpy_setup_callbacks)
+    {
+      if (p.first != nullptr && p.first () < 0)
+	return false;
+    }
 
 #define GDB_PY_DEFINE_EVENT_TYPE(name, py_name, doc, base)	\
   if (gdbpy_initialize_event_generic (&name##_event_object_type, py_name) < 0) \
-- 
2.25.4


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/3] gdb/python: break dependencies between gdbpy_initialize_* functions
  2022-10-02 16:53 ` [PATCH 1/3] gdb/python: break dependencies between gdbpy_initialize_* functions Andrew Burgess
@ 2022-10-14 17:06   ` Tom Tromey
  2022-10-20 15:58     ` Andrew Burgess
  0 siblings, 1 reply; 13+ messages in thread
From: Tom Tromey @ 2022-10-14 17:06 UTC (permalink / raw)
  To: Andrew Burgess via Gdb-patches

>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes:

Andrew> To me this is better, the dependency is now really obvious, but also,
Andrew> we no longer care in which order gdbpy_initialize_record and
Andrew> gdbpy_initialize_instruction are called.

I agree, I think this should go in.  Thank you.

Tom

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/3] gdb/python: break more dependencies between gdbpy_initialize_* functions
  2022-10-02 16:53 ` [PATCH 2/3] gdb/python: break more " Andrew Burgess
@ 2022-10-14 17:06   ` Tom Tromey
  2022-10-20 15:59     ` Andrew Burgess
  0 siblings, 1 reply; 13+ messages in thread
From: Tom Tromey @ 2022-10-14 17:06 UTC (permalink / raw)
  To: Andrew Burgess via Gdb-patches

>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes:

Andrew> After this commit a new function gdbpy_breakpoint_init_breakpoint_type
Andrew> exists, this function ensures that breakpoint_object_type has been
Andrew> initialized, and can be called from any gdbpy_initialize_* function.

Andrew> I feel that this change makes the dependency explicit, which I think
Andrew> is a good thing.

Me too.  Thanks for doing this, I think you should check it in.

Tom

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 3/3] gdb/python: add gdbpy_register_subsystem mechanism
  2022-10-02 16:53 ` [PATCH 3/3] gdb/python: add gdbpy_register_subsystem mechanism Andrew Burgess
@ 2022-10-14 17:20   ` Tom Tromey
  2022-10-21 13:17     ` [PATCHv2] gdb/python: add mechanism to manage Python initialization functions Andrew Burgess
  0 siblings, 1 reply; 13+ messages in thread
From: Tom Tromey @ 2022-10-14 17:20 UTC (permalink / raw)
  To: Andrew Burgess via Gdb-patches

>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes:

Andrew> All callbacks registered through gdbpy_register_subsystem are added to
Andrew> a vector, and in python.c we iterate over the vector and all the
Andrew> various functions as needed.

Andrew> The only question is when should gdbpy_register_subsystem be called?
Andrew> The answer I think is to make use of GDB's existing _initialize_*
Andrew> function mechanism.  A few of the python sub-system files already
Andrew> include an _initialize_* function, but most needed to have one added.

This approach seems a little weird to me, in that it uses the
_initialize_* functions to hook into gdb's existing initialization
approach, but then registers a second layer of initialization functions
in a vector to be called a little later.

What if, instead, something like make-init-c was used, but specifically
for Python initialization (and finalization) functions?

Tom

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/3] gdb/python: break dependencies between gdbpy_initialize_* functions
  2022-10-14 17:06   ` Tom Tromey
@ 2022-10-20 15:58     ` Andrew Burgess
  0 siblings, 0 replies; 13+ messages in thread
From: Andrew Burgess @ 2022-10-20 15:58 UTC (permalink / raw)
  To: Tom Tromey, Andrew Burgess via Gdb-patches

Tom Tromey <tom@tromey.com> writes:

>>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes:
>
> Andrew> To me this is better, the dependency is now really obvious, but also,
> Andrew> we no longer care in which order gdbpy_initialize_record and
> Andrew> gdbpy_initialize_instruction are called.
>
> I agree, I think this should go in.  Thank you.

Thanks, I've pushed this patch.

Andrew


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/3] gdb/python: break more dependencies between gdbpy_initialize_* functions
  2022-10-14 17:06   ` Tom Tromey
@ 2022-10-20 15:59     ` Andrew Burgess
  0 siblings, 0 replies; 13+ messages in thread
From: Andrew Burgess @ 2022-10-20 15:59 UTC (permalink / raw)
  To: Tom Tromey, Andrew Burgess via Gdb-patches

Tom Tromey <tom@tromey.com> writes:

>>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes:
>
> Andrew> After this commit a new function gdbpy_breakpoint_init_breakpoint_type
> Andrew> exists, this function ensures that breakpoint_object_type has been
> Andrew> initialized, and can be called from any gdbpy_initialize_* function.
>
> Andrew> I feel that this change makes the dependency explicit, which I think
> Andrew> is a good thing.
>
> Me too.  Thanks for doing this, I think you should check it in.

I've pushed this patch, and will have a think about what to do with
patch 3/3.

Thanks,
Andrew


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCHv2] gdb/python: add mechanism to manage Python initialization functions
  2022-10-14 17:20   ` Tom Tromey
@ 2022-10-21 13:17     ` Andrew Burgess
  2023-04-17 15:26       ` Tom Tromey
  0 siblings, 1 reply; 13+ messages in thread
From: Andrew Burgess @ 2022-10-21 13:17 UTC (permalink / raw)
  To: gdb-patches

Hi Tom,

Thanks for your feedback.

I'm not a huge fan of our existing make-init-c system.  I think, now
we've moved to C++ there are "in-lanaguage" ways we could achieve the
same result without having to generate code.  Though I'm have no plans
to try and change the existing _initialize_* mechanism.

That said, I'm not super keen to add more of the same.

However, I did take a pass at using make-init-c.  I changed the Python
functions to _gdbpy_initialize_* and _gdbpy_finalize_*, and extended
make-init-c to find these and add them to two new functions.  I did
get this working, but there's still a bunch of things I'd need to
figure out... but the more I worked on this the less I liked it.

.... so, I have a something different to propose.  I'm not sure you're
going to like it any more than my first attempt.  It still has a two
phase process, but it doesn't make use of _initialize_* any more.
Instead I'm not using global object construction to register the
callbacks.

If you don't like this any more than my first attempt then I'll finish
off the make-init-c patch, but I thought I'd post this first and see
what you thought.

Thanks,
Andrew

---

Currently, when we add a new python sub-system to GDB,
e.g. py-inferior.c, we end up having to create a new function like
gdbpy_initialize_inferior, which then has to be called from the
function do_start_initialization in python.c.

In some cases (or currently just the one case), like py-micmd.c, we
have two functions gdbpy_initialize_micommands, and
gdbpy_finalize_micommands, with the second being called from
finalize_python which is also in python.c.

This commit proposes a mechanism to manage these initialization and
finalization calls, this means that adding a new Python subsystem will
no longer require changes to python.c or python-internal.h, instead,
the initialization and finalization functions will be registered
directly from the sub-system file, e.g. py-inferior.c, or py-micmd.c.

The initialization and finalization functions are managed through a
new class gdbpy_initialize_file in python-internal.h.  This class
contains a single global vector of all the initialization and
finalization functions.

In each Python sub-system we create a new gdbpy_initialize_file
object, the object constructor takes care of registering the two
callback functions.

Now from python.c we can call functions on the gdbpy_initialize_file
class which take care of walking the callback list and invoking each
callback in turn.

To slightly simplify the Python sub-system files I added a new macro
GDBPY_INITIALIZE_FILE, which hides the need to create an object.  We
can now just do this:

  GDBPY_INITIALIZE_FILE (gdbpy_initialize_registers);

One possible problem with this change is that there is now no
guaranteed ordering of how the various sub-systems are initialized (or
finalized).  To try and avoid dependencies creeping in I have added a
use of the environment variable GDB_REVERSE_INIT_FUNCTIONS, this is
the same environment variable used in the generated init.c file.

Just like with init.c, when this environment variable is set we
reverse the list of Python initialization (and finalization)
functions.  As there is already a test that starts GDB with the
environment variable set then this should offer some level of
protection against dependencies creeping in - though for full
protection I guess we'd need to run all gdb.python/*.exp tests with
the variable set.

I have tested this patch with the environment variable set, and saw no
regressions, so I think we are fine right now.

One other change of note was for gdbpy_initialize_gdb_readline, this
function previously returned void.  In order to make this function
have the correct signature I've updated its return type to int, and we
now return 0 to indicate success.

All of the other initialize (and finalize) functions have been made
static within their respective sub-system files.

There should be no user visible changes after this commit.
---
 gdb/python/py-arch.c             |   6 +-
 gdb/python/py-auto-load.c        |   4 +-
 gdb/python/py-block.c            |   4 +-
 gdb/python/py-breakpoint.c       |   7 +-
 gdb/python/py-cmd.c              |   4 +-
 gdb/python/py-connection.c       |   4 +-
 gdb/python/py-disasm.c           |   6 +-
 gdb/python/py-event.c            |   4 +-
 gdb/python/py-evtregistry.c      |   4 +-
 gdb/python/py-finishbreakpoint.c |   6 +-
 gdb/python/py-frame.c            |   4 +-
 gdb/python/py-function.c         |   4 +-
 gdb/python/py-gdb-readline.c     |   5 +-
 gdb/python/py-inferior.c         |   6 +-
 gdb/python/py-infthread.c        |   6 +-
 gdb/python/py-instruction.c      |   4 +-
 gdb/python/py-lazy-string.c      |   4 +-
 gdb/python/py-linetable.c        |   4 +-
 gdb/python/py-membuf.c           |   6 +-
 gdb/python/py-micmd.c            |   9 +-
 gdb/python/py-objfile.c          |   4 +-
 gdb/python/py-param.c            |   4 +-
 gdb/python/py-progspace.c        |   4 +-
 gdb/python/py-record-btrace.c    |   4 +-
 gdb/python/py-record.c           |   4 +-
 gdb/python/py-registers.c        |   6 +-
 gdb/python/py-symbol.c           |   4 +-
 gdb/python/py-symtab.c           |   4 +-
 gdb/python/py-tui.c              |   4 +-
 gdb/python/py-type.c             |   4 +-
 gdb/python/py-unwind.c           |  34 +++---
 gdb/python/py-value.c            |   4 +-
 gdb/python/py-xmethods.c         |   4 +-
 gdb/python/python-internal.h     | 184 +++++++++++++++++++------------
 gdb/python/python.c              |  44 ++------
 35 files changed, 258 insertions(+), 155 deletions(-)

diff --git a/gdb/python/py-arch.c b/gdb/python/py-arch.c
index cf0978560f9..44b9195a77e 100644
--- a/gdb/python/py-arch.c
+++ b/gdb/python/py-arch.c
@@ -344,7 +344,7 @@ gdbpy_all_architecture_names (PyObject *self, PyObject *args)
 
 /* Initializes the Architecture class in the gdb module.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_arch (void)
 {
   arch_object_type.tp_new = PyType_GenericNew;
@@ -355,6 +355,10 @@ gdbpy_initialize_arch (void)
 				 (PyObject *) &arch_object_type);
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_arch);
+
+\f
+
 static PyMethodDef arch_object_methods [] = {
   { "name", archpy_name, METH_NOARGS,
     "name () -> String.\n\
diff --git a/gdb/python/py-auto-load.c b/gdb/python/py-auto-load.c
index 5d60460683a..cc53fa7c0a8 100644
--- a/gdb/python/py-auto-load.c
+++ b/gdb/python/py-auto-load.c
@@ -56,7 +56,7 @@ info_auto_load_python_scripts (const char *pattern, int from_tty)
   auto_load_info_scripts (pattern, from_tty, &extension_language_python);
 }
 \f
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_auto_load (void)
 {
   add_setshow_boolean_cmd ("python-scripts", class_support,
@@ -95,3 +95,5 @@ Print the list of automatically loaded Python scripts, deprecated."));
 
   return 0;
 }
+
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_auto_load);
diff --git a/gdb/python/py-block.c b/gdb/python/py-block.c
index b9aea3aca69..c6fad3cedc0 100644
--- a/gdb/python/py-block.c
+++ b/gdb/python/py-block.c
@@ -424,7 +424,7 @@ blpy_iter_is_valid (PyObject *self, PyObject *args)
   Py_RETURN_TRUE;
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_blocks (void)
 {
   block_object_type.tp_new = PyType_GenericNew;
@@ -443,6 +443,8 @@ gdbpy_initialize_blocks (void)
 				 (PyObject *) &block_syms_iterator_object_type);
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_blocks);
+
 \f
 
 static PyMethodDef block_object_methods[] = {
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index 7a757432948..108152b84e9 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -1231,7 +1231,7 @@ gdbpy_breakpoint_modified (struct breakpoint *b)
 \f
 
 /* Initialize the Python breakpoint code.  */
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_breakpoints (void)
 {
   int i;
@@ -1271,7 +1271,7 @@ gdbpy_initialize_breakpoints (void)
 
 /* Initialize the Python BreakpointLocation code.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_breakpoint_locations ()
 {
   if (PyType_Ready (&breakpoint_location_object_type) < 0)
@@ -1435,6 +1435,9 @@ _initialize_py_breakpoint ()
 	&setdebuglist, &showdebuglist);
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_breakpoints);
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_breakpoint_locations);
+
 /* Python function to set the enabled state of a breakpoint location.  */
 
 static int
diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c
index 5cc392af175..8715c53cfca 100644
--- a/gdb/python/py-cmd.c
+++ b/gdb/python/py-cmd.c
@@ -551,7 +551,7 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
 
 /* Initialize the 'commands' code.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_commands (void)
 {
   int i;
@@ -601,6 +601,8 @@ gdbpy_initialize_commands (void)
   return 0;
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_commands);
+
 \f
 
 static PyMethodDef cmdpy_object_methods[] =
diff --git a/gdb/python/py-connection.c b/gdb/python/py-connection.c
index 84660414dd0..7b8a77f087b 100644
--- a/gdb/python/py-connection.c
+++ b/gdb/python/py-connection.c
@@ -285,7 +285,7 @@ connpy_get_connection_details (PyObject *self, void *closure)
 
 /* Python specific initialization for this file.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_connection (void)
 {
   if (PyType_Ready (&connection_object_type) < 0)
@@ -447,6 +447,8 @@ _initialize_py_connection ()
 					     "py-connection");
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_connection);
+
 /* Methods for the gdb.TargetConnection object type.  */
 
 static PyMethodDef connection_object_methods[] =
diff --git a/gdb/python/py-disasm.c b/gdb/python/py-disasm.c
index c37452fcf72..9b89f4a4424 100644
--- a/gdb/python/py-disasm.c
+++ b/gdb/python/py-disasm.c
@@ -971,7 +971,7 @@ static struct PyModuleDef python_disassembler_module_def =
 
 /* Called to initialize the Python structures in this file.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_disasm ()
 {
   /* Create the _gdb.disassembler module, and add it to the _gdb module.  */
@@ -1005,6 +1005,10 @@ gdbpy_initialize_disasm ()
   return 0;
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_disasm);
+
+\f
+
 /* Describe the gdb.disassembler.DisassembleInfo type.  */
 
 PyTypeObject disasm_info_object_type = {
diff --git a/gdb/python/py-event.c b/gdb/python/py-event.c
index 4d8a0b909c0..e8e788b4788 100644
--- a/gdb/python/py-event.c
+++ b/gdb/python/py-event.c
@@ -54,7 +54,7 @@ evpy_add_attribute (PyObject *event, const char *name, PyObject *attr)
 
 /* Initialize the Python event code.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_event (void)
 {
   return gdbpy_initialize_event_generic (&event_object_type,
@@ -114,6 +114,8 @@ evpy_emit_event (PyObject *event,
   return 0;
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_event);
+
 static gdb_PyGetSetDef event_object_getset[] =
 {
   { "__dict__", gdb_py_generic_dict, NULL,
diff --git a/gdb/python/py-evtregistry.c b/gdb/python/py-evtregistry.c
index f3a7f0ca244..535cfc694a3 100644
--- a/gdb/python/py-evtregistry.c
+++ b/gdb/python/py-evtregistry.c
@@ -102,7 +102,7 @@ evregpy_dealloc (PyObject *self)
 
 /* Initialize the Python event registry code.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_eventregistry (void)
 {
   if (PyType_Ready (&eventregistry_object_type) < 0)
@@ -123,6 +123,8 @@ evregpy_no_listeners_p (eventregistry_object *registry)
   return registry == nullptr || PyList_Size (registry->callbacks) == 0;
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_eventregistry);
+
 static PyMethodDef eventregistry_object_methods[] =
 {
   { "connect", evregpy_connect, METH_VARARGS, "Add function" },
diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c
index fdbff5cf6bf..523f3113dde 100644
--- a/gdb/python/py-finishbreakpoint.c
+++ b/gdb/python/py-finishbreakpoint.c
@@ -400,7 +400,7 @@ bpfinishpy_handle_exit (struct inferior *inf)
 
 /* Initialize the Python finish breakpoint code.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_finishbreakpoints (void)
 {
   if (!gdbpy_breakpoint_init_breakpoint_type ())
@@ -421,6 +421,10 @@ gdbpy_initialize_finishbreakpoints (void)
   return 0;
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_finishbreakpoints);
+
+\f
+
 static gdb_PyGetSetDef finish_breakpoint_object_getset[] = {
   { "return_value", bpfinishpy_get_returnvalue, NULL,
   "gdb.Value object representing the return value, if any. \
diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c
index cbce9457755..8bc2c5b4001 100644
--- a/gdb/python/py-frame.c
+++ b/gdb/python/py-frame.c
@@ -713,7 +713,7 @@ frapy_richcompare (PyObject *self, PyObject *other, int op)
 
 /* Sets up the Frame API in the gdb module.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_frames (void)
 {
   frame_object_type.tp_new = PyType_GenericNew;
@@ -745,6 +745,8 @@ gdbpy_initialize_frames (void)
 				 (PyObject *) &frame_object_type);
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_frames);
+
 \f
 
 static PyMethodDef frame_object_methods[] = {
diff --git a/gdb/python/py-function.c b/gdb/python/py-function.c
index c314ee5da71..2a00c5bf0da 100644
--- a/gdb/python/py-function.c
+++ b/gdb/python/py-function.c
@@ -134,7 +134,7 @@ fnpy_init (PyObject *self, PyObject *args, PyObject *kwds)
 
 /* Initialize internal function support.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_functions (void)
 {
   fnpy_object_type.tp_new = PyType_GenericNew;
@@ -145,6 +145,8 @@ gdbpy_initialize_functions (void)
 				 (PyObject *) &fnpy_object_type);
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_functions);
+
 \f
 
 PyTypeObject fnpy_object_type =
diff --git a/gdb/python/py-gdb-readline.c b/gdb/python/py-gdb-readline.c
index af388d5ed72..21d79498555 100644
--- a/gdb/python/py-gdb-readline.c
+++ b/gdb/python/py-gdb-readline.c
@@ -85,7 +85,7 @@ gdbpy_readline_wrapper (FILE *sys_stdin, FILE *sys_stdout,
 
 /* Initialize Python readline support.  */
 
-void
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_gdb_readline (void)
 {
   /* Python's readline module conflicts with GDB's use of readline
@@ -109,5 +109,8 @@ class GdbRemoveReadlineFinder:\n\
 sys.meta_path.append(GdbRemoveReadlineFinder())\n\
 ") == 0)
     PyOS_ReadlineFunctionPointer = gdbpy_readline_wrapper;
+
+  return 0;
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_gdb_readline);
diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c
index 8847a6d9308..c521b1b9c61 100644
--- a/gdb/python/py-inferior.c
+++ b/gdb/python/py-inferior.c
@@ -833,7 +833,7 @@ gdbpy_selected_inferior (PyObject *self, PyObject *args)
 	  inferior_to_inferior_object (current_inferior ()).release ());
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_inferior (void)
 {
   if (PyType_Ready (&inferior_object_type) < 0)
@@ -869,6 +869,10 @@ gdbpy_initialize_inferior (void)
   return 0;
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_inferior);
+
+\f
+
 static gdb_PyGetSetDef inferior_object_getset[] =
 {
   { "num", infpy_get_num, NULL, "ID of inferior, as assigned by GDB.", NULL },
diff --git a/gdb/python/py-infthread.c b/gdb/python/py-infthread.c
index 34f60526ac9..3ecb8d278ff 100644
--- a/gdb/python/py-infthread.c
+++ b/gdb/python/py-infthread.c
@@ -361,7 +361,7 @@ gdbpy_selected_thread (PyObject *self, PyObject *args)
   Py_RETURN_NONE;
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_thread (void)
 {
   if (PyType_Ready (&thread_object_type) < 0)
@@ -371,6 +371,10 @@ gdbpy_initialize_thread (void)
 				 (PyObject *) &thread_object_type);
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_thread);
+
+\f
+
 static gdb_PyGetSetDef thread_object_getset[] =
 {
   { "name", thpy_get_name, thpy_set_name,
diff --git a/gdb/python/py-instruction.c b/gdb/python/py-instruction.c
index fee5bba4015..b0afd363890 100644
--- a/gdb/python/py-instruction.c
+++ b/gdb/python/py-instruction.c
@@ -81,10 +81,12 @@ py_insn_get_insn_type ()
 
 /* Sets up the gdb.Instruction type.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_instruction (void)
 {
   if (py_insn_get_insn_type () == nullptr)
     return -1;
   return 0;
 }
+
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_instruction);
diff --git a/gdb/python/py-lazy-string.c b/gdb/python/py-lazy-string.c
index 8cd8b91e91b..7bf294fff70 100644
--- a/gdb/python/py-lazy-string.c
+++ b/gdb/python/py-lazy-string.c
@@ -229,7 +229,7 @@ gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
   return (PyObject *) str_obj;
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_lazy_string (void)
 {
   if (PyType_Ready (&lazy_string_object_type) < 0)
@@ -291,6 +291,8 @@ gdbpy_extract_lazy_string (PyObject *string, CORE_ADDR *addr,
   encoding->reset (lazy->encoding ? xstrdup (lazy->encoding) : NULL);
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_lazy_string);
+
 \f
 
 static PyMethodDef lazy_string_object_methods[] = {
diff --git a/gdb/python/py-linetable.c b/gdb/python/py-linetable.c
index 8e545febb17..51c13ad3228 100644
--- a/gdb/python/py-linetable.c
+++ b/gdb/python/py-linetable.c
@@ -286,7 +286,7 @@ ltpy_dealloc (PyObject *self)
 /* Initialize LineTable, LineTableEntry and LineTableIterator
    objects.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_linetable (void)
 {
   if (PyType_Ready (&linetable_object_type) < 0)
@@ -446,6 +446,8 @@ ltpy_iter_is_valid (PyObject *self, PyObject *args)
   Py_RETURN_TRUE;
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_linetable);
+
 \f
 
 static PyMethodDef linetable_object_methods[] = {
diff --git a/gdb/python/py-membuf.c b/gdb/python/py-membuf.c
index d2a059a0e34..054b31ecd7b 100644
--- a/gdb/python/py-membuf.c
+++ b/gdb/python/py-membuf.c
@@ -99,7 +99,7 @@ get_buffer (PyObject *self, Py_buffer *buf, int flags)
 
 /* General Python initialization callback.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_membuf (void)
 {
   membuf_object_type.tp_new = PyType_GenericNew;
@@ -110,6 +110,10 @@ gdbpy_initialize_membuf (void)
 				 (PyObject *) &membuf_object_type);
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_membuf);
+
+\f
+
 static PyBufferProcs buffer_procs =
 {
   get_buffer
diff --git a/gdb/python/py-micmd.c b/gdb/python/py-micmd.c
index 79e2575f789..ccd2578e3d3 100644
--- a/gdb/python/py-micmd.c
+++ b/gdb/python/py-micmd.c
@@ -595,7 +595,7 @@ micmdpy_dealloc (PyObject *obj)
 
 /* Python initialization for the MI commands components.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_micommands ()
 {
   micmdpy_object_type.tp_new = PyType_GenericNew;
@@ -614,7 +614,9 @@ gdbpy_initialize_micommands ()
   return 0;
 }
 
-void
+/* Cleanup just before GDB shuts down the Python interpreter.  */
+
+static void
 gdbpy_finalize_micommands ()
 {
   /* mi_command_py objects hold references to micmdpy_object objects.  They must
@@ -737,3 +739,6 @@ _initialize_py_micmd ()
      show_pymicmd_debug,
      &setdebuglist, &showdebuglist);
 }
+
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_micommands,
+		       gdbpy_finalize_micommands);
diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
index c278925531b..c1f97dddb33 100644
--- a/gdb/python/py-objfile.c
+++ b/gdb/python/py-objfile.c
@@ -704,7 +704,7 @@ objfile_to_objfile_object (struct objfile *objfile)
   return gdbpy_ref<>::new_reference (result);
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_objfile (void)
 {
   if (PyType_Ready (&objfile_object_type) < 0)
@@ -714,6 +714,8 @@ gdbpy_initialize_objfile (void)
 				 (PyObject *) &objfile_object_type);
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_objfile);
+
 \f
 
 static PyMethodDef objfile_object_methods[] =
diff --git a/gdb/python/py-param.c b/gdb/python/py-param.c
index cab0c563b0e..e461d33f6fb 100644
--- a/gdb/python/py-param.c
+++ b/gdb/python/py-param.c
@@ -832,7 +832,7 @@ parmpy_dealloc (PyObject *obj)
 }
 
 /* Initialize the 'parameters' module.  */
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_parameters (void)
 {
   int i;
@@ -860,6 +860,8 @@ gdbpy_initialize_parameters (void)
 				 (PyObject *) &parmpy_object_type);
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_parameters);
+
 \f
 
 PyTypeObject parmpy_object_type =
diff --git a/gdb/python/py-progspace.c b/gdb/python/py-progspace.c
index 4eb33e8292f..d957abfdf11 100644
--- a/gdb/python/py-progspace.c
+++ b/gdb/python/py-progspace.c
@@ -529,7 +529,7 @@ gdbpy_is_progspace (PyObject *obj)
   return PyObject_TypeCheck (obj, &pspace_object_type);
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_pspace (void)
 {
   if (PyType_Ready (&pspace_object_type) < 0)
@@ -539,6 +539,8 @@ gdbpy_initialize_pspace (void)
 				 (PyObject *) &pspace_object_type);
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_pspace);
+
 \f
 
 static gdb_PyGetSetDef pspace_getset[] =
diff --git a/gdb/python/py-record-btrace.c b/gdb/python/py-record-btrace.c
index 85401010f0a..beefd7e8148 100644
--- a/gdb/python/py-record-btrace.c
+++ b/gdb/python/py-record-btrace.c
@@ -816,7 +816,7 @@ static PyMappingMethods btpy_list_mapping_methods =
 
 /* Sets up the btrace record API.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_btrace (void)
 {
   btpy_list_type.tp_new = PyType_GenericNew;
@@ -837,3 +837,5 @@ gdbpy_initialize_btrace (void)
 
   return PyType_Ready (&btpy_list_type);
 }
+
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_btrace);
diff --git a/gdb/python/py-record.c b/gdb/python/py-record.c
index fd5cfee84eb..d9a43ced43a 100644
--- a/gdb/python/py-record.c
+++ b/gdb/python/py-record.c
@@ -544,7 +544,7 @@ static gdb_PyGetSetDef recpy_gap_getset[] = {
 
 /* Sets up the record API in the gdb module.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_record (void)
 {
   recpy_record_type.tp_new = PyType_GenericNew;
@@ -648,3 +648,5 @@ gdbpy_stop_recording (PyObject *self, PyObject *args)
 
   Py_RETURN_NONE;
 }
+
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_record);
diff --git a/gdb/python/py-registers.c b/gdb/python/py-registers.c
index fe7481cea9e..9cca2e53524 100644
--- a/gdb/python/py-registers.c
+++ b/gdb/python/py-registers.c
@@ -427,7 +427,7 @@ gdbpy_parse_register_id (struct gdbarch *gdbarch, PyObject *pyo_reg_id,
 
 /* Initializes the new Python classes from this file in the gdb module.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_registers ()
 {
   register_descriptor_object_type.tp_new = PyType_GenericNew;
@@ -462,6 +462,10 @@ gdbpy_initialize_registers ()
 	   (PyObject *) &register_descriptor_iterator_object_type));
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_registers);
+
+\f
+
 static PyMethodDef register_descriptor_iterator_object_methods [] = {
   { "find", (PyCFunction) register_descriptor_iter_find,
     METH_VARARGS | METH_KEYWORDS,
diff --git a/gdb/python/py-symbol.c b/gdb/python/py-symbol.c
index 93c86964f3e..191986274b5 100644
--- a/gdb/python/py-symbol.c
+++ b/gdb/python/py-symbol.c
@@ -611,7 +611,7 @@ gdbpy_lookup_static_symbols (PyObject *self, PyObject *args, PyObject *kw)
   return return_list.release ();
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_symbols (void)
 {
   if (PyType_Ready (&symbol_object_type) < 0)
@@ -680,6 +680,8 @@ gdbpy_initialize_symbols (void)
 				 (PyObject *) &symbol_object_type);
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_symbols);
+
 \f
 
 static gdb_PyGetSetDef symbol_object_getset[] = {
diff --git a/gdb/python/py-symtab.c b/gdb/python/py-symtab.c
index 03c274dfff6..ae443311332 100644
--- a/gdb/python/py-symtab.c
+++ b/gdb/python/py-symtab.c
@@ -509,7 +509,7 @@ symtab_object_to_symtab (PyObject *obj)
   return ((symtab_object *) obj)->symtab;
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_symtabs (void)
 {
   symtab_object_type.tp_new = PyType_GenericNew;
@@ -528,6 +528,8 @@ gdbpy_initialize_symtabs (void)
 				 (PyObject *) &sal_object_type);
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_symtabs);
+
 \f
 
 static gdb_PyGetSetDef symtab_object_getset[] = {
diff --git a/gdb/python/py-tui.c b/gdb/python/py-tui.c
index 6a92251a705..d07ffccf0c3 100644
--- a/gdb/python/py-tui.c
+++ b/gdb/python/py-tui.c
@@ -561,7 +561,7 @@ PyTypeObject gdbpy_tui_window_object_type =
 
 /* Initialize this module.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_tui ()
 {
 #ifdef TUI
@@ -572,3 +572,5 @@ gdbpy_initialize_tui ()
 
   return 0;
 }
+
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_tui);
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index 3e558dee7ad..7ef0e129aaa 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -1465,7 +1465,7 @@ gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw)
   return type_to_type_object (type);
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_types (void)
 {
   if (PyType_Ready (&type_object_type) < 0)
@@ -1493,6 +1493,8 @@ gdbpy_initialize_types (void)
 				 (PyObject *) &field_object_type);
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_types);
+
 \f
 
 static gdb_PyGetSetDef type_object_getset[] =
diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
index 20b0ab460cc..8a0c0d89892 100644
--- a/gdb/python/py-unwind.c
+++ b/gdb/python/py-unwind.c
@@ -682,23 +682,9 @@ pyuw_on_new_gdbarch (struct gdbarch *newarch)
     }
 }
 
-void _initialize_py_unwind ();
-void
-_initialize_py_unwind ()
-{
-  add_setshow_boolean_cmd
-      ("py-unwind", class_maintenance, &pyuw_debug,
-	_("Set Python unwinder debugging."),
-	_("Show Python unwinder debugging."),
-	_("When on, Python unwinder debugging is enabled."),
-	NULL,
-	show_pyuw_debug,
-	&setdebuglist, &showdebuglist);
-}
-
 /* Initialize unwind machinery.  */
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_unwind (void)
 {
   gdb::observers::architecture_changed.attach (pyuw_on_new_gdbarch,
@@ -717,6 +703,24 @@ gdbpy_initialize_unwind (void)
       (PyObject *) &unwind_info_object_type);
 }
 
+void _initialize_py_unwind ();
+void
+_initialize_py_unwind ()
+{
+  add_setshow_boolean_cmd
+      ("py-unwind", class_maintenance, &pyuw_debug,
+	_("Set Python unwinder debugging."),
+	_("Show Python unwinder debugging."),
+	_("When on, Python unwinder debugging is enabled."),
+	NULL,
+	show_pyuw_debug,
+	&setdebuglist, &showdebuglist);
+}
+
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_unwind);
+
+\f
+
 static PyMethodDef pending_frame_object_methods[] =
 {
   { "read_register", pending_framepy_read_register, METH_VARARGS,
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index 92a15304c34..7aab09db073 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -2059,7 +2059,7 @@ gdbpy_is_value_object (PyObject *obj)
   return PyObject_TypeCheck (obj, &value_object_type);
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_values (void)
 {
   if (PyType_Ready (&value_object_type) < 0)
@@ -2069,6 +2069,8 @@ gdbpy_initialize_values (void)
 				 (PyObject *) &value_object_type);
 }
 
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_values);
+
 \f
 
 static gdb_PyGetSetDef value_object_getset[] = {
diff --git a/gdb/python/py-xmethods.c b/gdb/python/py-xmethods.c
index 1467e52a960..e236ac5514b 100644
--- a/gdb/python/py-xmethods.c
+++ b/gdb/python/py-xmethods.c
@@ -598,7 +598,7 @@ python_xmethod_worker::python_xmethod_worker (PyObject *py_worker,
   Py_INCREF (this_type);
 }
 
-int
+static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_xmethods (void)
 {
   py_match_method_name = PyUnicode_FromString (match_method_name);
@@ -612,3 +612,5 @@ gdbpy_initialize_xmethods (void)
 
   return 1;
 }
+
+GDBPY_INITIALIZE_FILE (gdbpy_initialize_xmethods);
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 06357cc8c0b..102a517f7e2 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -489,76 +489,120 @@ struct gdbarch *arch_object_to_gdbarch (PyObject *obj);
 
 extern struct program_space *progspace_object_to_program_space (PyObject *obj);
 
-void gdbpy_initialize_gdb_readline (void);
-int gdbpy_initialize_auto_load (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_values (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_frames (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_instruction (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_btrace (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_record (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_symtabs (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_commands (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_symbols (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_symtabs (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_blocks (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_types (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_functions (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_pspace (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_objfile (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_breakpoints (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_breakpoint_locations ()
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_finishbreakpoints (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_lazy_string (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_linetable (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_parameters (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_thread (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_inferior (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_eventregistry (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_event (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_arch (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_registers ()
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_xmethods (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_unwind (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_tui ()
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_membuf ()
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_connection ()
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_micommands (void)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-void gdbpy_finalize_micommands ();
-int gdbpy_initialize_disasm ()
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
+/* A class for managing the initialization, and finalization functions
+   from all Python files (e.g. gdb/python/py-*.c).
+
+   Within any Python file, create an instance of this class, passing in
+   the initialization function, and, optionally, the finalization
+   function.
+
+   These functions are added to a single global list of functions, which
+   can then be called from do_start_initialization and finalize_python
+   (see python.c) to initialize all the Python files within GDB.  */
+
+class gdbpy_initialize_file
+{
+  /* The type of a function that can be called just after GDB has setup the
+     Python interpreter.  This function will setup any additional Python
+     state required by a particular subsystem.  Return 0 if the setup was
+     successful, or return -1 if setup failed, in which case a Python
+     exception should have been raised.  */
+
+  using gdbpy_initialize_file_ftype = int (*) (void);
+
+  /* The type of a function that can be called just before GDB shuts down
+     the Python interpreter.  This function can cleanup an Python state
+     that is cached within GDB, for example, if GDB is holding any
+     references to Python objects, these should be released before the
+     Python interpreter is shut down.
+
+     There is no error return in this case.  This function is only called
+     when GDB is already shutting down.  The function should make a best
+     effort to clean up, and then return.  */
+
+  using gdbpy_finalize_file_ftype = void (*) (void);
+
+  /* The type for an initialization and finalization function pair.  */
+
+  using callback_pair_t = std::pair<gdbpy_initialize_file_ftype,
+				    gdbpy_finalize_file_ftype>;
+
+  /* Return the vector of callbacks.  The vector is defined as a static
+     variable within this function so that it will be initialized the first
+     time this function is called.  This is important, as this function is
+     called as part of the global object initialization process; if the
+     vector was a static variable within this class then we could not
+     guarantee that it had been initialized before it was used.  */
+
+  static std::vector<callback_pair_t> &
+  callbacks ()
+  {
+    static std::vector<callback_pair_t> list;
+    return list;
+  }
+
+public:
+
+  /* Register the initialization (INIT) and finalization (FINI) functions
+     for a Python file.  See the comments on the function types above for
+     when these functions will be called.
+
+     Either of these functions can be nullptr, in which case no function
+     will be called.
+
+     The FINI argument is optional, and defaults to nullptr (no function to
+     call).  */
+
+  gdbpy_initialize_file (gdbpy_initialize_file_ftype init,
+			 gdbpy_finalize_file_ftype fini = nullptr)
+  {
+    callbacks ().emplace_back (init, fini);
+  }
+
+  /* Run all the Python file initialize functions and return true.  If any
+     of the initialize functions fails then this function returns false.
+     In the case of failure it is undefined how many of the initialize
+     functions will have been called.  */
+
+  static bool
+  initialize_all ()
+  {
+    /* The initialize_all function should only be called once.  The
+       following check reverses the global list, which will effect this
+       initialize_all call, as well as the later finalize_all call.
+
+       The environment variable checked here is the same as the one checked
+       in the generated init.c file.  */
+    if (getenv ("GDB_REVERSE_INIT_FUNCTIONS") != nullptr)
+      std::reverse (callbacks ().begin (), callbacks ().end ());
+
+    for (const auto &p : gdbpy_initialize_file::callbacks ())
+      {
+	if (p.first != nullptr && p.first () < 0)
+	  return false;
+      }
+    return true;
+  }
+
+  /* Run all the Python file finalize functions.  */
+
+  static void
+  finalize_all ()
+  {
+    for (const auto &p : gdbpy_initialize_file::callbacks ())
+      {
+	if (p.second != nullptr)
+	  p.second ();
+      }
+  }
+};
+
+/* Macro to simplify registering the initialization and finalization
+   functions for a Python file.  */
+
+#define GDBPY_INITIALIZE_FILE(INIT, ...)				\
+  static gdbpy_initialize_file						\
+    CONCAT(gdbpy_initialize_file_obj_, __LINE__) (INIT, ##__VA_ARGS__)
 
 PyMODINIT_FUNC gdbpy_events_mod_func ();
 
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 29f2010ee8e..c3da8deb4aa 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -1931,7 +1931,10 @@ finalize_python (void *ignore)
   (void) PyGILState_Ensure ();
   gdbpy_enter::finalize ();
 
-  gdbpy_finalize_micommands ();
+  /* Every item in GDBPY_SETUP_CALLBACKS is a pair.  The second item in
+     the pair is (when not nullptr), a function to call to cleanup a
+     particular Python subsystem within GDB.  */
+  gdbpy_initialize_file::finalize_all ();
 
   Py_Finalize ();
 
@@ -2119,41 +2122,10 @@ do_start_initialization ()
 				 gdbpy_gdberror_exc) < 0)
     return false;
 
-  gdbpy_initialize_gdb_readline ();
-
-  if (gdbpy_initialize_auto_load () < 0
-      || gdbpy_initialize_values () < 0
-      || gdbpy_initialize_disasm () < 0
-      || gdbpy_initialize_frames () < 0
-      || gdbpy_initialize_commands () < 0
-      || gdbpy_initialize_instruction () < 0
-      || gdbpy_initialize_record () < 0
-      || gdbpy_initialize_btrace () < 0
-      || gdbpy_initialize_symbols () < 0
-      || gdbpy_initialize_symtabs () < 0
-      || gdbpy_initialize_blocks () < 0
-      || gdbpy_initialize_functions () < 0
-      || gdbpy_initialize_parameters () < 0
-      || gdbpy_initialize_types () < 0
-      || gdbpy_initialize_pspace () < 0
-      || gdbpy_initialize_objfile () < 0
-      || gdbpy_initialize_breakpoints () < 0
-      || gdbpy_initialize_breakpoint_locations () < 0
-      || gdbpy_initialize_finishbreakpoints () < 0
-      || gdbpy_initialize_lazy_string () < 0
-      || gdbpy_initialize_linetable () < 0
-      || gdbpy_initialize_thread () < 0
-      || gdbpy_initialize_inferior () < 0
-      || gdbpy_initialize_eventregistry () < 0
-      || gdbpy_initialize_event () < 0
-      || gdbpy_initialize_arch () < 0
-      || gdbpy_initialize_registers () < 0
-      || gdbpy_initialize_xmethods () < 0
-      || gdbpy_initialize_unwind () < 0
-      || gdbpy_initialize_membuf () < 0
-      || gdbpy_initialize_connection () < 0
-      || gdbpy_initialize_tui () < 0
-      || gdbpy_initialize_micommands () < 0)
+  /* Every item in GDBPY_SETUP_CALLBACKS is a pair.  The first item in the
+     pair is (when not nullptr), a function to call to setup a particular
+     Python subsystem within GDB.  */
+  if (!gdbpy_initialize_file::initialize_all ())
     return false;
 
 #define GDB_PY_DEFINE_EVENT_TYPE(name, py_name, doc, base)	\
-- 
2.25.4


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCHv2] gdb/python: add mechanism to manage Python initialization functions
  2022-10-21 13:17     ` [PATCHv2] gdb/python: add mechanism to manage Python initialization functions Andrew Burgess
@ 2023-04-17 15:26       ` Tom Tromey
  2023-05-05 17:27         ` Andrew Burgess
  0 siblings, 1 reply; 13+ messages in thread
From: Tom Tromey @ 2023-04-17 15:26 UTC (permalink / raw)
  To: Andrew Burgess via Gdb-patches; +Cc: Andrew Burgess

>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes:

I saw this today and realized I'd forgotten to reply to it.  It wasn't
intentional.

Andrew> I'm not a huge fan of our existing make-init-c system.  I think, now
Andrew> we've moved to C++ there are "in-lanaguage" ways we could achieve the
Andrew> same result without having to generate code.  Though I'm have no plans
Andrew> to try and change the existing _initialize_* mechanism.

Seems fair.  I was worried about the static initialization problems
we've hit before, but I see you have fixed those.  And actually your
patch makes me want to do the same for unit tests, so we can move the
gdbsupport unit tests into gdbsupport/ where (IMO) they belong.

Andrew> If you don't like this any more than my first attempt then I'll finish
Andrew> off the make-init-c patch, but I thought I'd post this first and see
Andrew> what you thought.

This looks good to me.

Reviewed-By: Tom Tromey <tom@tromey.com>

Andrew> -int
Andrew> +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
Andrew>  gdbpy_initialize_arch (void)

Not a problem you need to address, but I'm not sure we can even run the
Python checker any more, now that gdb is using C++ (and things like
gdbpy_ref<>).

thanks,
Tom

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCHv2] gdb/python: add mechanism to manage Python initialization functions
  2023-04-17 15:26       ` Tom Tromey
@ 2023-05-05 17:27         ` Andrew Burgess
  2023-05-05 20:07           ` Tom Tromey
  0 siblings, 1 reply; 13+ messages in thread
From: Andrew Burgess @ 2023-05-05 17:27 UTC (permalink / raw)
  To: Tom Tromey, Andrew Burgess via Gdb-patches

Tom Tromey <tom@tromey.com> writes:

>>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes:
>
> I saw this today and realized I'd forgotten to reply to it.  It wasn't
> intentional.
>
> Andrew> I'm not a huge fan of our existing make-init-c system.  I think, now
> Andrew> we've moved to C++ there are "in-lanaguage" ways we could achieve the
> Andrew> same result without having to generate code.  Though I'm have no plans
> Andrew> to try and change the existing _initialize_* mechanism.
>
> Seems fair.  I was worried about the static initialization problems
> we've hit before, but I see you have fixed those.  And actually your
> patch makes me want to do the same for unit tests, so we can move the
> gdbsupport unit tests into gdbsupport/ where (IMO) they belong.
>
> Andrew> If you don't like this any more than my first attempt then I'll finish
> Andrew> off the make-init-c patch, but I thought I'd post this first and see
> Andrew> what you thought.
>
> This looks good to me.
>
> Reviewed-By: Tom Tromey <tom@tromey.com>

Thanks for getting back to this.  I've gone ahead and pushed this now.

>
> Andrew> -int
> Andrew> +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
> Andrew>  gdbpy_initialize_arch (void)
>
> Not a problem you need to address, but I'm not sure we can even run the
> Python checker any more, now that gdb is using C++ (and things like
> gdbpy_ref<>).

I wondered about this too, but wasn't sure how to check.

Would be nice to clean these up one day if they are no longer useful.

Thanks,
Andrew


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCHv2] gdb/python: add mechanism to manage Python initialization functions
  2023-05-05 17:27         ` Andrew Burgess
@ 2023-05-05 20:07           ` Tom Tromey
  0 siblings, 0 replies; 13+ messages in thread
From: Tom Tromey @ 2023-05-05 20:07 UTC (permalink / raw)
  To: Andrew Burgess via Gdb-patches; +Cc: Tom Tromey, Andrew Burgess

>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes:

>> Not a problem you need to address, but I'm not sure we can even run the
>> Python checker any more, now that gdb is using C++ (and things like
>> gdbpy_ref<>).

Andrew> I wondered about this too, but wasn't sure how to check.

We should really ask David Malcolm.  I am not 100% sure myself, since I
haven't really been following the progress of the checker.

Tom

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2023-05-05 20:07 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-02 16:53 [PATCH 0/3] New mechanism to initialise Python components in GDB Andrew Burgess
2022-10-02 16:53 ` [PATCH 1/3] gdb/python: break dependencies between gdbpy_initialize_* functions Andrew Burgess
2022-10-14 17:06   ` Tom Tromey
2022-10-20 15:58     ` Andrew Burgess
2022-10-02 16:53 ` [PATCH 2/3] gdb/python: break more " Andrew Burgess
2022-10-14 17:06   ` Tom Tromey
2022-10-20 15:59     ` Andrew Burgess
2022-10-02 16:53 ` [PATCH 3/3] gdb/python: add gdbpy_register_subsystem mechanism Andrew Burgess
2022-10-14 17:20   ` Tom Tromey
2022-10-21 13:17     ` [PATCHv2] gdb/python: add mechanism to manage Python initialization functions Andrew Burgess
2023-04-17 15:26       ` Tom Tromey
2023-05-05 17:27         ` Andrew Burgess
2023-05-05 20:07           ` Tom Tromey

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).