Skip to content

Commit

Permalink
Mute noisy diagnostics with Python debug builds, avoid post-Finalize …
Browse files Browse the repository at this point in the history
…Python API access by pre-Finalize cleanup of modules. This avoids an assertion in Python debug builds and is a better style anyway.
  • Loading branch information
Matthias Koefferlein committed Sep 15, 2024
1 parent 53b7c98 commit 20d599b
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 11 deletions.
21 changes: 21 additions & 0 deletions src/pya/pya/pya.cc
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,10 @@ PythonInterpreter::PythonInterpreter (bool embedded)

PythonInterpreter::~PythonInterpreter ()
{
for (auto m = m_modules.begin (); m != m_modules.end (); ++m) {
(*m)->cleanup ();
}

m_stdout_channel = PythonRef ();
m_stderr_channel = PythonRef ();
m_stdout = PythonPtr ();
Expand All @@ -370,6 +374,23 @@ PythonInterpreter::~PythonInterpreter ()
if (m_embedded) {
Py_Finalize ();
}

for (auto m = m_modules.begin (); m != m_modules.end (); ++m) {
delete *m;
}
m_modules.clear ();
}

void
PythonInterpreter::register_module (pya::PythonModule *module)
{
for (auto m = m_modules.begin (); m != m_modules.end (); ++m) {
if (*m == module) {
return; // already registered
}
}

m_modules.push_back (module);
}

char *
Expand Down
10 changes: 9 additions & 1 deletion src/pya/pya/pya.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ class PYA_PUBLIC PythonInterpreter
*/
~PythonInterpreter ();

/**
* @brief Registers a module
*
* The registered modules are cleaned up before the interpreter shuts down. The interpreter takes
* ownership of the module object.
*/
void register_module (pya::PythonModule *module);

/**
* @brief Add the given path to the search path
*/
Expand Down Expand Up @@ -279,7 +287,7 @@ class PYA_PUBLIC PythonInterpreter
std::map<PyObject *, size_t> m_file_id_map;
std::wstring mp_py3_app_name;
bool m_embedded;
std::unique_ptr<pya::PythonModule> m_pya_module;
std::vector<pya::PythonModule *> m_modules;
};

}
Expand Down
3 changes: 3 additions & 0 deletions src/pya/pya/pyaCallables.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ pya_object_deallocate (PyObject *self)
// we better work around it.
++self->ob_refcnt;

// Mute Python warnings in debug case
PyObject_GC_UnTrack (self);

PYAObjectBase *p = PYAObjectBase::from_pyobject (self);
p->~PYAObjectBase ();
Py_TYPE (self)->tp_free (self);
Expand Down
16 changes: 10 additions & 6 deletions src/pya/pya/pyaModule.cc
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,6 @@ PythonModule::PythonModule ()

PythonModule::~PythonModule ()
{
PYAObjectBase::clear_callbacks_cache ();

// the Python objects were probably deleted by Python itself as it exited -
// don't try to delete them again.
mp_module.release ();

while (!m_methods_heap.empty ()) {
delete m_methods_heap.back ();
m_methods_heap.pop_back ();
Expand All @@ -93,6 +87,16 @@ PythonModule::~PythonModule ()
}
}

void
PythonModule::cleanup ()
{
// the Python objects are probably deleted by Python itself as it exits -
// don't try to delete them again in the destructor.
mp_module.release ();

PYAObjectBase::clear_callbacks_cache ();
}

PyObject *
PythonModule::module ()
{
Expand Down
6 changes: 6 additions & 0 deletions src/pya/pya/pyaModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ class PYA_PUBLIC PythonModule
*/
~PythonModule ();

/**
* @brief Clean up the module
* This method is called by the interpreter before Py_Finalize
*/
void cleanup ();

/**
* @brief Initializes the module
* This entry point is for external use where the module has not been created yet
Expand Down
14 changes: 10 additions & 4 deletions src/pymod/pymodHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,20 @@

#include "pyaModule.h"
#include "pyaUtils.h"
#include "pya.h"

#include "gsi.h"
#include "gsiExpression.h"

static PyObject *
module_init (const char *pymod_name, const char *mod_name, const char *mod_description)
{
static pya::PythonModule module;
if (! pya::PythonInterpreter::instance ()) {
return 0;
}

pya::PythonModule *module = new pya::PythonModule ();
pya::PythonInterpreter::instance ()->register_module (module);

PYA_TRY

Expand All @@ -50,10 +56,10 @@ module_init (const char *pymod_name, const char *mod_name, const char *mod_descr
// required for the tiling processor for example
gsi::initialize_expressions ();

module.init (pymod_name, mod_description);
module.make_classes (mod_name);
module->init (pymod_name, mod_description);
module->make_classes (mod_name);

return module.take_module ();
return module->take_module ();

PYA_CATCH_ANYWHERE

Expand Down

0 comments on commit 20d599b

Please sign in to comment.