Fix T39445: Async LibLoad Crash
authorMitchell Stokes <mogurijin@gmail.com>
Wed, 16 Apr 2014 08:15:40 +0000 (01:15 -0700)
committerMitchell Stokes <mogurijin@gmail.com>
Wed, 16 Apr 2014 08:15:40 +0000 (01:15 -0700)
There was some deadlock due to trying manage Python's GIL. Instead of
continuing to fight with it, anything needing to call into Python while
conversion during lib loading is just delayed until it can be done in
the main thread.

source/gameengine/Converter/BL_BlenderDataConversion.cpp
source/gameengine/Converter/KX_ConvertControllers.cpp
source/gameengine/Converter/KX_ConvertControllers.h
source/gameengine/Ketsji/KX_Scene.cpp

index b283330266fc338f0ed1a1af92e84c660f363943..f03f4a915311a7a1842a40164875f6c27eb057a4 100644 (file)
@@ -2874,7 +2874,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
                struct Object* blenderobj = gameobj->GetBlenderObject();
                int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0;
                bool isInActiveLayer = (blenderobj->lay & layerMask)!=0;
-               BL_ConvertControllers(blenderobj,gameobj,logicmgr, layerMask,isInActiveLayer,converter);
+               BL_ConvertControllers(blenderobj,gameobj,logicmgr, layerMask,isInActiveLayer,converter, libloading);
        }
        for ( i=0;i<logicbrick_conversionlist->GetCount();i++)
        {
index 5d3d0f33bec122b0fd1269f85f1a7b9fe7ed72b1..ab5f1611cb9de43afad4bcc154e6a1330369fad7 100644 (file)
@@ -94,7 +94,8 @@ void BL_ConvertControllers(
        SCA_LogicManager* logicmgr,
        int activeLayerBitInfo,
        bool isInActiveLayer,
-       KX_BlenderSceneConverter* converter
+       KX_BlenderSceneConverter* converter,
+       bool libloading
 ) {
        int uniqueint=0;
        int count = 0;
@@ -157,8 +158,9 @@ void BL_ConvertControllers(
                                SCA_PythonController* pyctrl = new SCA_PythonController(gameobj, pycont->mode);
                                gamecontroller = pyctrl;
 #ifdef WITH_PYTHON
-                               PyGILState_STATE gstate = PyGILState_Ensure();
-                               pyctrl->SetNamespace(converter->GetPyNamespace());
+                               // When libloading, this is delayed to KX_Scene::MergeScene_LogicBrick to avoid GIL issues
+                               if (!libloading)
+                                       pyctrl->SetNamespace(converter->GetPyNamespace());
                                
                                if (pycont->mode==SCA_PythonController::SCA_PYEXEC_SCRIPT) {
                                        if (pycont->text)
@@ -185,8 +187,6 @@ void BL_ConvertControllers(
                                                pyctrl->SetDebug(true);
                                        }
                                }
-                               
-                               PyGILState_Release(gstate);
 #endif // WITH_PYTHON
 
                                break;
@@ -219,8 +219,8 @@ void BL_ConvertControllers(
                        converter->RegisterGameController(gamecontroller, bcontr);
 
 #ifdef WITH_PYTHON
-                       PyGILState_STATE gstate = PyGILState_Ensure();
-                       if (bcontr->type==CONT_PYTHON) {
+                       // When libloading, this is delayed to KX_Scene::MergeScene_LogicBrick to avoid GIL issues
+                       if (!libloading && bcontr->type==CONT_PYTHON) {
                                SCA_PythonController *pyctrl= static_cast<SCA_PythonController*>(gamecontroller);
                                /* not strictly needed but gives syntax errors early on and
                                 * gives more predictable performance for larger scripts */
@@ -235,7 +235,6 @@ void BL_ConvertControllers(
                                }
                        }
 
-                       PyGILState_Release(gstate);
 #endif // WITH_PYTHON
 
                        //done with gamecontroller
index 817a49e1b2f3077d589c04dce38baecfdf0295ed..babe3e2e73f4183bc227d91f620859bfe6602543 100644 (file)
@@ -40,7 +40,8 @@ void BL_ConvertControllers(
        class SCA_LogicManager* logicmgr,
        int activeLayerBitInfo,
        bool isInActiveLayer, 
-       class KX_BlenderSceneConverter* converter
+       class KX_BlenderSceneConverter* converter,
+    bool libloading
 );
 
 #endif  /* __KX_CONVERTCONTROLLERS_H__ */
index 2e560290732f271dc4aecb5f6cf7b4174ae6588a..64ba17f49f6d150895a47006df34c76cdedf1443 100644 (file)
@@ -49,6 +49,7 @@
 //#include "SCA_RandomEventManager.h"
 //#include "KX_RayEventManager.h"
 #include "SCA_2DFilterActuator.h"
+#include "SCA_PythonController.h"
 #include "KX_TouchEventManager.h"
 #include "SCA_KeyboardManager.h"
 #include "SCA_MouseManager.h"
@@ -1900,6 +1901,19 @@ static void MergeScene_LogicBrick(SCA_ILogicBrick* brick, KX_Scene *to)
        if (filter_actuator) {
                filter_actuator->SetScene(to);
        }
+
+#ifdef WITH_PYTHON
+       // Python must be called from the main thread unless we want to deal
+       // with GIL issues. So, this is delayed until here in case of async
+       // libload (originally in KX_ConvertControllers)
+       SCA_PythonController *pyctrl = dynamic_cast<SCA_PythonController*>(brick);
+       if (pyctrl) {
+               pyctrl->SetNamespace(KX_GetActiveEngine()->GetPyNamespace());
+
+               if (pyctrl->m_mode==SCA_PythonController::SCA_PYEXEC_SCRIPT)
+                       pyctrl->Compile();
+       }
+#endif
 }
 
 #ifdef WITH_BULLET