Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python "leak" fix #1889

Merged
merged 3 commits into from Dec 6, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions xbmc/interfaces/legacy/Addon.cpp
Expand Up @@ -33,9 +33,9 @@ namespace XBMCAddon
{
namespace xbmcaddon
{
String Addon::getDefaultId() { return languageHook == NULL ? emptyString : languageHook->getAddonId(); }
String Addon::getDefaultId() { return languageHook == NULL ? emptyString : languageHook->GetAddonId(); }

String Addon::getAddonVersion() { return languageHook == NULL ? emptyString : languageHook->getAddonVersion(); }
String Addon::getAddonVersion() { return languageHook == NULL ? emptyString : languageHook->GetAddonVersion(); }

Addon::Addon(const char* cid) throw (AddonException) : AddonClass("Addon")
{
Expand Down
2 changes: 1 addition & 1 deletion xbmc/interfaces/legacy/AddonCallback.h
Expand Up @@ -45,7 +45,7 @@ namespace XBMCAddon
{
// if there is a LanguageHook, it should be set already.
if (languageHook != NULL)
setHandler(languageHook->getCallbackHandler());
setHandler(languageHook->GetCallbackHandler());
}
virtual ~AddonCallback();

Expand Down
4 changes: 2 additions & 2 deletions xbmc/interfaces/legacy/AddonClass.cpp
Expand Up @@ -61,7 +61,7 @@ namespace XBMCAddon
#endif

// check to see if we have a language hook that was prepared for this instantiation
languageHook = LanguageHook::getLanguageHook();
languageHook = LanguageHook::GetLanguageHook();
if (languageHook != NULL)
{
languageHook->Acquire();
Expand All @@ -70,7 +70,7 @@ namespace XBMCAddon
// this AddonClass (actually - its subclass - but whatever). So we
// will now reset the Tls. This avoids issues if the constructor of the
// subclass throws an exception.
LanguageHook::clearLanguageHook();
LanguageHook::ClearLanguageHook();
}
}

Expand Down
3 changes: 3 additions & 0 deletions xbmc/interfaces/legacy/AddonClass.h
Expand Up @@ -101,6 +101,9 @@ namespace XBMCAddon
AddonClass(const char* classname);
virtual ~AddonClass();

inline const String& GetClassname() const { return classname; }
inline LanguageHook* GetLanguageHook() { return languageHook; }

/**
* This method should be called while holding a Synchronize
* on the object. It will prevent the deallocation during
Expand Down
4 changes: 2 additions & 2 deletions xbmc/interfaces/legacy/CallbackHandler.cpp
Expand Up @@ -84,7 +84,7 @@ namespace XBMCAddon
AddonClass::Ref<AsynchCallbackMessage> p(*iter);

// only call when we are in the right thread state
if(p->handler->isThreadStateOk())
if(p->handler->isStateOk(p->cb->getObject()))
{
// remove it from the queue. No matter what we're done with
// this. Even if it doesn't execute for some reason.
Expand Down Expand Up @@ -140,7 +140,7 @@ namespace XBMCAddon
{
AddonClass::Ref<AsynchCallbackMessage> p(*iter);

if(p->handler->shouldRemoveCallback(userData))
if(p->handler->shouldRemoveCallback(p->cb->getObject(),userData))
{
#ifdef ENABLE_TRACE_API
CLog::Log(LOGDEBUG,"%sNEWADDON removing callback 0x%lx for PyThreadState 0x%lx from queue", _tg.getSpaces(),(long)(p->cb.get()) ,(long)userData);
Expand Down
4 changes: 2 additions & 2 deletions xbmc/interfaces/legacy/CallbackHandler.h
Expand Up @@ -64,8 +64,8 @@ namespace XBMCAddon
static void makePendingCalls();
static void clearPendingCalls(void* userData);

virtual bool isThreadStateOk() = 0;
virtual bool shouldRemoveCallback(void* userData) = 0;
virtual bool isStateOk(AddonClass* obj) = 0;
virtual bool shouldRemoveCallback(AddonClass* obj, void* userData) = 0;
};

}
6 changes: 3 additions & 3 deletions xbmc/interfaces/legacy/LanguageHook.cpp
Expand Up @@ -33,19 +33,19 @@ namespace XBMCAddon
static bool threadLocalInitilialized = false;
static xbmcutil::InitFlag initer(threadLocalInitilialized);

void LanguageHook::setLanguageHook(LanguageHook* languageHook)
void LanguageHook::SetLanguageHook(LanguageHook* languageHook)
{
TRACE;
languageHook->Acquire();
addonLanguageHookTls.set(languageHook);
}

LanguageHook* LanguageHook::getLanguageHook()
LanguageHook* LanguageHook::GetLanguageHook()
{
return threadLocalInitilialized ? addonLanguageHookTls.get() : NULL;
}

void LanguageHook::clearLanguageHook()
void LanguageHook::ClearLanguageHook()
{
LanguageHook* lh = addonLanguageHookTls.get();
addonLanguageHookTls.set(NULL);
Expand Down
54 changes: 27 additions & 27 deletions xbmc/interfaces/legacy/LanguageHook.h
Expand Up @@ -58,7 +58,7 @@ namespace XBMCAddon
* Python to run by using Py_BEGIN_ALLOW_THREADS. This is
* the place to put that functionality
*/
virtual void delayedCallOpen() { }
virtual void DelayedCallOpen() { }

/**
* If the scripting language needs special handling for calls
Expand All @@ -72,15 +72,15 @@ namespace XBMCAddon
* state using Py_END_ALLOW_THREADS. This is the place to put
* that functionality
*/
virtual void delayedCallClose() { }
virtual void DelayedCallClose() { }

virtual void makePendingCalls() {}
virtual void MakePendingCalls() {}

/**
* For scripting languages that need a global callback handler, this
* method should be overloaded to supply one.
*/
virtual CallbackHandler* getCallbackHandler() { return NULL; }
virtual CallbackHandler* GetCallbackHandler() { return NULL; }

/**
* This is a callback method that can be overriden to receive a callback
Expand All @@ -89,7 +89,7 @@ namespace XBMCAddon
* cannot assume the subclasses have been built or that calling a
* virtual function on the AddonClass will work as expected.
*/
virtual void constructing(AddonClass* beingConstructed) { }
virtual void Constructing(AddonClass* beingConstructed) { }

/**
* This is a callback method that can be overriden to receive a callback
Expand All @@ -98,7 +98,7 @@ namespace XBMCAddon
* should assume the subclasses have been torn down and that calling a
* virtual function on the AddonClass will not work as expected.
*/
virtual void destructing(AddonClass* beingDestructed) { }
virtual void Destructing(AddonClass* beingDestructed) { }

/**
* This method should be done a different way but since the only other way
Expand All @@ -110,23 +110,23 @@ namespace XBMCAddon
* to use scripting language specific calls. So until I figure out a
* better way to do this, this is how I need to retrieve it.
*/
virtual String getAddonId() { return emptyString; }
virtual String getAddonVersion() { return emptyString; }

virtual void registerPlayerCallback(IPlayerCallback* player) = 0;
virtual void unregisterPlayerCallback(IPlayerCallback* player) = 0;
virtual void registerMonitorCallback(XBMCAddon::xbmc::Monitor* player) = 0;
virtual void unregisterMonitorCallback(XBMCAddon::xbmc::Monitor* player) = 0;
virtual bool waitForEvent(CEvent& hEvent, unsigned int milliseconds) = 0;

static void setLanguageHook(LanguageHook* languageHook);
static LanguageHook* getLanguageHook();
static void clearLanguageHook();
virtual String GetAddonId() { return emptyString; }
virtual String GetAddonVersion() { return emptyString; }

virtual void RegisterPlayerCallback(IPlayerCallback* player) = 0;
virtual void UnregisterPlayerCallback(IPlayerCallback* player) = 0;
virtual void RegisterMonitorCallback(XBMCAddon::xbmc::Monitor* player) = 0;
virtual void UnregisterMonitorCallback(XBMCAddon::xbmc::Monitor* player) = 0;
virtual bool WaitForEvent(CEvent& hEvent, unsigned int milliseconds) = 0;

static void SetLanguageHook(LanguageHook* languageHook);
static LanguageHook* GetLanguageHook();
static void ClearLanguageHook();
};

/**
* This class can be used to access the language hook's delayedCallOpen
* and delayedCallClose. It should be used whenever an API method
* This class can be used to access the language hook's DelayedCallOpen
* and DelayedCallClose. It should be used whenever an API method
* is written such that it can block for an indefinite amount of time
* since certain scripting languages (like Python) need to do extra
* work for delayed calls (like free the python locks and handle
Expand All @@ -139,15 +139,15 @@ namespace XBMCAddon

public:
inline DelayedCallGuard(LanguageHook* languageHook_) : languageHook(languageHook_), clearOnExit(false)
{ if (languageHook) languageHook->delayedCallOpen(); }
{ if (languageHook) languageHook->DelayedCallOpen(); }

inline DelayedCallGuard() : languageHook(LanguageHook::getLanguageHook()), clearOnExit(false)
{ if (languageHook) languageHook->delayedCallOpen(); }
inline DelayedCallGuard() : languageHook(LanguageHook::GetLanguageHook()), clearOnExit(false)
{ if (languageHook) languageHook->DelayedCallOpen(); }

inline ~DelayedCallGuard()
{
if (clearOnExit) LanguageHook::clearLanguageHook();
if (languageHook) languageHook->delayedCallClose();
if (clearOnExit) LanguageHook::ClearLanguageHook();
if (languageHook) languageHook->DelayedCallClose();
}

inline LanguageHook* getLanguageHook() { return languageHook; }
Expand All @@ -156,8 +156,8 @@ namespace XBMCAddon
class SetLanguageHookGuard
{
public:
inline SetLanguageHookGuard(LanguageHook* languageHook) { LanguageHook::setLanguageHook(languageHook); }
inline ~SetLanguageHookGuard() { LanguageHook::clearLanguageHook(); }
inline SetLanguageHookGuard(LanguageHook* languageHook) { LanguageHook::SetLanguageHook(languageHook); }
inline ~SetLanguageHookGuard() { LanguageHook::ClearLanguageHook(); }
};

}
Expand Down
2 changes: 1 addition & 1 deletion xbmc/interfaces/legacy/ModuleXbmc.cpp
Expand Up @@ -155,7 +155,7 @@ namespace XBMCAddon
::Sleep(nextSleep);
}
if (lh != NULL)
lh->makePendingCalls();
lh->MakePendingCalls();
}
}

Expand Down
6 changes: 3 additions & 3 deletions xbmc/interfaces/legacy/Monitor.cpp
Expand Up @@ -29,8 +29,8 @@ namespace XBMCAddon
{
if (languageHook)
{
Id = languageHook->getAddonId();
languageHook->registerMonitorCallback(this);
Id = languageHook->GetAddonId();
languageHook->RegisterMonitorCallback(this);
}
}

Expand All @@ -42,7 +42,7 @@ namespace XBMCAddon
if (languageHook)
{
DelayedCallGuard dc;
languageHook->unregisterMonitorCallback(this);
languageHook->UnregisterMonitorCallback(this);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions xbmc/interfaces/legacy/Player.cpp
Expand Up @@ -50,7 +50,7 @@ namespace XBMCAddon
if (languageHook)
{
DelayedCallGuard dc(languageHook);
languageHook->registerPlayerCallback(this);
languageHook->RegisterPlayerCallback(this);
}
}

Expand All @@ -62,7 +62,7 @@ namespace XBMCAddon
if (languageHook)
{
DelayedCallGuard dc(languageHook);
languageHook->unregisterPlayerCallback(this);
languageHook->UnregisterPlayerCallback(this);
}
}

Expand Down
6 changes: 3 additions & 3 deletions xbmc/interfaces/legacy/Window.cpp
Expand Up @@ -397,7 +397,7 @@ namespace XBMCAddon
{
TRACE;
// DO NOT MAKE THIS A DELAYED CALL!!!!
bool ret = languageHook == NULL ? m_actionEvent.WaitMSec(milliseconds) : languageHook->waitForEvent(m_actionEvent,milliseconds);
bool ret = languageHook == NULL ? m_actionEvent.WaitMSec(milliseconds) : languageHook->WaitForEvent(m_actionEvent,milliseconds);
if (ret)
m_actionEvent.Reset();
return ret;
Expand Down Expand Up @@ -706,7 +706,7 @@ namespace XBMCAddon
// Window_Close(self, NULL);
// break;
// }
languageHook->makePendingCalls(); // MakePendingCalls
languageHook->MakePendingCalls(); // MakePendingCalls

bool stillWaiting;
do
Expand All @@ -715,7 +715,7 @@ namespace XBMCAddon
DelayedCallGuard dcguard(languageHook);
stillWaiting = WaitForActionEvent(100) ? false : true;
}
languageHook->makePendingCalls();
languageHook->MakePendingCalls();
} while (stillWaiting);
}
}
Expand Down
22 changes: 18 additions & 4 deletions xbmc/interfaces/python/CallbackHandler.cpp
Expand Up @@ -20,6 +20,7 @@
*/

#include "CallbackHandler.h"
#include "LanguageHook.h"

namespace XBMCAddon
{
Expand All @@ -42,10 +43,18 @@ namespace XBMCAddon
* Now we are answering the question as to whether or not we are in the
* PyThreadState that we were in when we started.
*/
bool PythonCallbackHandler::isThreadStateOk()
bool PythonCallbackHandler::isStateOk(AddonClass* obj)
{
TRACE;
return objectThreadState == PyThreadState_Get();
PyThreadState* state = PyThreadState_Get();
if (objectThreadState == state)
{
// make sure the interpreter is still active.
AddonClass::Ref<XBMCAddon::Python::LanguageHook> lh(XBMCAddon::Python::LanguageHook::GetIfExists(state->interp));
if (lh.isNotNull() && lh->HasRegisteredAddonClassInstance(obj) && lh.get() == obj->GetLanguageHook())
return true;
}
return false;
}

/**
Expand All @@ -55,10 +64,15 @@ namespace XBMCAddon
* TODO: This is a stupid way to get this information back to the handler.
* there should be a more language neutral means.
*/
bool PythonCallbackHandler::shouldRemoveCallback(void* threadState)
bool PythonCallbackHandler::shouldRemoveCallback(AddonClass* obj, void* threadState)
{
TRACE;
return threadState == objectThreadState;
if (threadState == objectThreadState)
return true;

// we also want to remove the callback if the language hook no longer exists.
// this is a belt-and-suspenders cleanup mechanism
return ! XBMCAddon::Python::LanguageHook::IsAddonClassInstanceRegistered(obj);
}
}
}
4 changes: 2 additions & 2 deletions xbmc/interfaces/python/CallbackHandler.h
Expand Up @@ -44,8 +44,8 @@ namespace XBMCAddon
* handling callbacks in the appropriate thread.
*/
PythonCallbackHandler();
virtual bool isThreadStateOk();
virtual bool shouldRemoveCallback(void* threadState);
virtual bool isStateOk(AddonClass* obj);
virtual bool shouldRemoveCallback(AddonClass* obj, void* threadState);
};
}
}