Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed crash of death when calling XBPyThread::stop() while inside a p…

…ython dialog's doModal()

When XBPyThread::stop() is called, a SystemExit exception is raised in Python script's threads, but the Python window "misses the memo". It continues calling PyXBMC_MakePendingCalls() ([1]), which XBMC continues populating with onAction events even though the event's thread has a SystemExit exception raised.

Eventually, as python objects are unloaded, the user-supplied onAction() will throw an exception. When this is caught ([2]), a call to PyErr_Print() seems to go on an object-freeing spree, but the deallocation of something naughty causes python26.dll (Win32) to invoke a "crash of death" immediately terminating the entire XBMC application.

The fix is to have doModal() check if the exception has been raised; if so, hide the window and return control to the python script. By having XBPyThread::stop() invoke g_pythonParser.PulseGlobalEvent() we can force doModal() to wake up immediately instead of laying dormant until another onAction event.

[1] https://github.com/xbmc/xbmc/blob/master/xbmc/interfaces/python/xbmcmodule/window.cpp#L540
[2] https://github.com/xbmc/xbmc/blob/master/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.cpp#L281
  • Loading branch information...
commit 469b420a696bc2969b5228605c6f4dd8fdb6d85b 1 parent d04e05e
@garbear garbear authored
View
3  xbmc/interfaces/python/XBPyThread.cpp
@@ -452,10 +452,13 @@ void XBPyThread::stop()
old = PyThreadState_Swap((PyThreadState*)m_threadState);
for(PyThreadState* state = ((PyThreadState*)m_threadState)->interp->tstate_head; state; state = state->next)
{
+ // Raise a SystemExit exception in python threads
Py_XDECREF(state->async_exc);
state->async_exc = PyExc_SystemExit;
Py_XINCREF(state->async_exc);
}
+ // If a dialog entered its doModal(), we need to wake it to see the exception
+ g_pythonParser.PulseGlobalEvent();
PyThreadState_Swap(old);
PyEval_ReleaseLock();
View
9 xbmc/interfaces/python/xbmcmodule/window.cpp
@@ -35,6 +35,7 @@
#include "Application.h"
#include "ApplicationMessenger.h"
#include "threads/SingleLock.h"
+#include "utils/log.h"
using namespace std;
@@ -537,6 +538,14 @@ namespace PYXBMC
while (self->bModal && !g_application.m_bStop)
{
+ // Check if XBPyThread::stop() raised a SystemExit exception
+ if (PyThreadState_Get()->async_exc == PyExc_SystemExit)
+ {
+ CLog::Log(LOGDEBUG, "PYTHON: doModal() encountered a SystemExit exception, closing window and returning");
+ Window_Close(self, NULL);
+ break;
+ }
+
PyXBMC_MakePendingCalls();
CPyThreadState pyState;
Please sign in to comment.
Something went wrong with that request. Please try again.