Skip to content
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.

  • Loading branch information...
1 parent d04e05e commit 469b420a696bc2969b5228605c6f4dd8fdb6d85b @garbear garbear committed
Showing with 12 additions and 0 deletions.
  1. +3 −0 xbmc/interfaces/python/XBPyThread.cpp
  2. +9 −0 xbmc/interfaces/python/xbmcmodule/window.cpp
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
state->async_exc = PyExc_SystemExit;
+ // If a dialog entered its doModal(), we need to wake it to see the exception
+ g_pythonParser.PulseGlobalEvent();
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;
+ }
CPyThreadState pyState;

0 comments on commit 469b420

Please sign in to comment.
Something went wrong with that request. Please try again.