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

FIX: GilSafeSingleLock is causing UI freeze when it cannot get the GIL back... #1204

Closed
wants to merge 1 commit into from
Closed
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
88 changes: 64 additions & 24 deletions xbmc/interfaces/python/xbmcmodule/window.cpp
Expand Up @@ -41,17 +41,7 @@ using namespace std;
#define ACTIVE_WINDOW g_windowManager.GetActiveWindow() #define ACTIVE_WINDOW g_windowManager.GetActiveWindow()




/** #ifdef __cplusplus
* A CSingleLock that will relinquish the GIL during the time
* it takes to obtain the CriticalSection
*/
class GilSafeSingleLock : public CPyThreadState, public CSingleLock
{
public:
GilSafeSingleLock(const CCriticalSection& critSec) : CPyThreadState(true), CSingleLock(critSec) { CPyThreadState::Restore(); }
};

#ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif


Expand All @@ -62,15 +52,18 @@ namespace PYXBMC
// used by Dialog to to create a new dialogWindow // used by Dialog to to create a new dialogWindow
bool Window_CreateNewWindow(Window* pWindow, bool bAsDialog) bool Window_CreateNewWindow(Window* pWindow, bool bAsDialog)
{ {
GilSafeSingleLock lock(g_graphicsContext); CPyThreadState state;


CSingleLock lock(g_graphicsContext);
if (pWindow->iWindowId != -1) if (pWindow->iWindowId != -1)
{ {
// user specified window id, use this one if it exists // user specified window id, use this one if it exists
// It is not possible to capture key presses or button presses // It is not possible to capture key presses or button presses
pWindow->pWindow = g_windowManager.GetWindow(pWindow->iWindowId); pWindow->pWindow = g_windowManager.GetWindow(pWindow->iWindowId);
if (!pWindow->pWindow) if (!pWindow->pWindow)
{ {
lock.Leave();
state.Restore();
PyErr_SetString(PyExc_ValueError, "Window id does not exist"); PyErr_SetString(PyExc_ValueError, "Window id does not exist");
return false; return false;
} }
Expand All @@ -84,6 +77,8 @@ namespace PYXBMC
// if window 13099 is in use it means python can't create more windows // if window 13099 is in use it means python can't create more windows
if (g_windowManager.GetWindow(WINDOW_PYTHON_END)) if (g_windowManager.GetWindow(WINDOW_PYTHON_END))
{ {
lock.Leave();
state.Restore();
PyErr_SetString(PyExc_Exception, "maximum number of windows reached"); PyErr_SetString(PyExc_Exception, "maximum number of windows reached");
return false; return false;
} }
Expand Down Expand Up @@ -111,6 +106,9 @@ namespace PYXBMC


g_windowManager.Add(pWindow->pWindow); g_windowManager.Add(pWindow->pWindow);
} }
lock.Leave();
state.Restore();

pWindow->iOldWindowId = 0; pWindow->iOldWindowId = 0;
pWindow->bModal = false; pWindow->bModal = false;
pWindow->iCurrentControlId = 3000; pWindow->iCurrentControlId = 3000;
Expand Down Expand Up @@ -139,13 +137,16 @@ namespace PYXBMC
} }


// lock xbmc GUI before accessing data from it // lock xbmc GUI before accessing data from it
GilSafeSingleLock lock(g_graphicsContext); CPyThreadState state;
CSingleLock lock(g_graphicsContext);


// check if control exists // check if control exists
CGUIControl* pGUIControl = (CGUIControl*)self->pWindow->GetControl(iControlId); CGUIControl* pGUIControl = (CGUIControl*)self->pWindow->GetControl(iControlId);
if (!pGUIControl) if (!pGUIControl)
{ {
// control does not exist. // control does not exist.
lock.Leave();
state.Restore();
CStdString error; CStdString error;
error.Format("Non-Existent Control %d",iControlId); error.Format("Non-Existent Control %d",iControlId);
PyErr_SetString(PyExc_TypeError, error.c_str()); PyErr_SetString(PyExc_TypeError, error.c_str());
Expand Down Expand Up @@ -282,6 +283,9 @@ namespace PYXBMC
break; break;
} }


lock.Leave();
state.Restore();

if (!pControl) if (!pControl)
{ {
// throw an exeption // throw an exeption
Expand Down Expand Up @@ -342,7 +346,9 @@ namespace PYXBMC


void Window_Dealloc(Window* self) void Window_Dealloc(Window* self)
{ {
GilSafeSingleLock lock(g_graphicsContext); CPyThreadState state;

CSingleLock lock(g_graphicsContext);
if (self->bIsPythonWindow) if (self->bIsPythonWindow)
{ {
// first change to an existing window // first change to an existing window
Expand Down Expand Up @@ -399,6 +405,8 @@ namespace PYXBMC
} }


lock.Leave(); lock.Leave();
state.Restore();

self->vecControls.clear(); self->vecControls.clear();
self->vecControls.~vector(); self->vecControls.~vector();
self->sFallBackPath.~string(); self->sFallBackPath.~string();
Expand Down Expand Up @@ -632,9 +640,13 @@ namespace PYXBMC
pControl->iParentId = self->iWindowId; pControl->iParentId = self->iWindowId;


{ // assign control id, if id is already in use, try next id { // assign control id, if id is already in use, try next id
GilSafeSingleLock lock(g_graphicsContext); CPyThreadState state;

CSingleLock lock(g_graphicsContext);
do pControl->iControlId = ++self->iCurrentControlId; do pControl->iControlId = ++self->iCurrentControlId;
while (self->pWindow->GetControl(pControl->iControlId)); while (self->pWindow->GetControl(pControl->iControlId));
lock.Leave();
state.Restore();
} }


// Control Label // Control Label
Expand Down Expand Up @@ -830,15 +842,18 @@ namespace PYXBMC


PyObject* Window_GetFocus(Window *self, PyObject *args) PyObject* Window_GetFocus(Window *self, PyObject *args)
{ {
GilSafeSingleLock lock(g_graphicsContext); CPyThreadState state;


CSingleLock lock(g_graphicsContext);
int iControlId = self->pWindow->GetFocusedControlID(); int iControlId = self->pWindow->GetFocusedControlID();
lock.Leave();

state.Restore();
if(iControlId == -1) if(iControlId == -1)
{ {
PyErr_SetString(PyExc_RuntimeError, "No control in this window has focus"); PyErr_SetString(PyExc_RuntimeError, "No control in this window has focus");
return NULL; return NULL;
} }
lock.Leave();


return (PyObject*)Window_GetControlById(self, iControlId); return (PyObject*)Window_GetControlById(self, iControlId);
} }
Expand All @@ -851,8 +866,13 @@ namespace PYXBMC


PyObject* Window_GetFocusId(Window *self, PyObject *args) PyObject* Window_GetFocusId(Window *self, PyObject *args)
{ {
GilSafeSingleLock lock(g_graphicsContext); CPyThreadState state;

CSingleLock lock(g_graphicsContext);
int iControlId = self->pWindow->GetFocusedControlID(); int iControlId = self->pWindow->GetFocusedControlID();
lock.Leave();

state.Restore();
if(iControlId == -1) if(iControlId == -1)
{ {
PyErr_SetString(PyExc_RuntimeError, "No control in this window has focus"); PyErr_SetString(PyExc_RuntimeError, "No control in this window has focus");
Expand Down Expand Up @@ -972,8 +992,13 @@ namespace PYXBMC
return NULL; return NULL;
} }


GilSafeSingleLock lock(g_graphicsContext); CPyThreadState state;

CSingleLock lock(g_graphicsContext);
self->pWindow->SetCoordsRes(g_settings.m_ResInfo[res]); self->pWindow->SetCoordsRes(g_settings.m_ResInfo[res]);
lock.Leave();

state.Restore();


Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
Expand Down Expand Up @@ -1056,9 +1081,14 @@ namespace PYXBMC
return NULL; } return NULL; }
if (!key) return NULL; if (!key) return NULL;


GilSafeSingleLock lock(g_graphicsContext); CPyThreadState state;

CSingleLock lock(g_graphicsContext);
CStdString lowerKey = key; CStdString lowerKey = key;
string value = self->pWindow->GetProperty(lowerKey.ToLower()).asString(); string value = self->pWindow->GetProperty(lowerKey.ToLower()).asString();
lock.Leave();

state.Restore();


return Py_BuildValue((char*)"s", value.c_str()); return Py_BuildValue((char*)"s", value.c_str());
} }
Expand Down Expand Up @@ -1091,10 +1121,15 @@ namespace PYXBMC
return NULL; return NULL;
} }
if (!key) return NULL; if (!key) return NULL;
GilSafeSingleLock lock(g_graphicsContext);


CPyThreadState state;

CSingleLock lock(g_graphicsContext);
CStdString lowerKey = key; CStdString lowerKey = key;
self->pWindow->SetProperty(lowerKey.ToLower(), ""); self->pWindow->SetProperty(lowerKey.ToLower(), "");
lock.Leave();

state.Restore();


Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
Expand All @@ -1109,8 +1144,13 @@ namespace PYXBMC


PyObject* Window_ClearProperties(Window *self, PyObject *args) PyObject* Window_ClearProperties(Window *self, PyObject *args)
{ {
GilSafeSingleLock lock(g_graphicsContext); CPyThreadState state;

CSingleLock lock(g_graphicsContext);
self->pWindow->ClearProperties(); self->pWindow->ClearProperties();
lock.Leave();

state.Restore();


Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
Expand Down