diff options
Diffstat (limited to 'xbmc/interfaces/python/XBPyThread.cpp')
-rw-r--r-- | xbmc/interfaces/python/XBPyThread.cpp | 54 |
1 files changed, 53 insertions, 1 deletions
diff --git a/xbmc/interfaces/python/XBPyThread.cpp b/xbmc/interfaces/python/XBPyThread.cpp index 1ffad6d49a..82ca80f782 100644 --- a/xbmc/interfaces/python/XBPyThread.cpp +++ b/xbmc/interfaces/python/XBPyThread.cpp @@ -42,6 +42,7 @@ #include "XBPyThread.h" #include "XBPython.h" +#include "LanguageHook.h" #include "interfaces/legacy/Exception.h" #include "interfaces/legacy/CallbackHandler.h" @@ -158,6 +159,9 @@ void XBPyThread::Process() // swap in my thread state PyThreadState_Swap(state); + XBMCAddon::AddonClass::Ref<XBMCAddon::Python::LanguageHook> languageHook(new XBMCAddon::Python::LanguageHook(state->interp)); + languageHook->RegisterMe(); + m_pExecuter->InitializeInterpreter(addon); CLog::Log(LOGDEBUG, "%s - The source file to load is %s", __FUNCTION__, m_source); @@ -369,8 +373,56 @@ void XBPyThread::Process() m_pExecuter->DeInitializeInterpreter(); Py_EndInterpreter(state); - PyThreadState_Swap(NULL); + // This is a total hack. Python doesn't necessarily release + // all of the objects associated with the interpreter when + // you end the interpreter. As a result there are objects + // managed by the windowing system that still receive events + // until python decides to clean them up. Python will eventually + // clean them up on the creation or ending of a subsequent + // interpreter. So we are going to keep creating and ending + // interpreters until we have no more python objects hanging + // around. + int countLimit; + for (countLimit = 0; languageHook->HasRegisteredAddonClasses() && countLimit < 10; countLimit++) + { + PyThreadState* tmpstate = Py_NewInterpreter(); + Py_EndInterpreter(tmpstate); + } + + // If necessary and successfull, debug log the results. + if (countLimit > 0 && !languageHook->HasRegisteredAddonClasses()) + CLog::Log(LOGDEBUG,"It took %d Py_NewInterpreter/Py_EndInterpreter calls" + " to clean up the classes leftover from running \"%s.\"", + countLimit,m_source); + + // If not successful, produce an error message detailing what's been left behind + if (languageHook->HasRegisteredAddonClasses()) + { + CStdString message; + message.Format("The python script \"%s\" has left several " + "classes in memory that should have been cleaned up. The classes include: ", + m_source); + + { XBMCAddon::AddonClass::Synchronize l(*(languageHook.get())); + std::set<XBMCAddon::AddonClass*>& acs = languageHook->GetRegisteredAddonClasses(); + bool firstTime = true; + for (std::set<XBMCAddon::AddonClass*>::iterator iter = acs.begin(); + iter != acs.end(); iter++) + { + if (!firstTime) message += ","; + else firstTime = false; + message += (*iter)->GetClassname().c_str(); + } + } + + CLog::Log(LOGERROR, "%s", message.c_str()); + } + + // unregister the language hook + languageHook->UnregisterMe(); + + PyThreadState_Swap(NULL); PyEval_ReleaseLock(); } |