From 59a30d822fe5ecfafbb5676b2058b7ff8d3760ed Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 22 Oct 2008 03:10:00 +0000 Subject: [PATCH] fix for [#17878] Scripts operating on blender objects don't clear memory after a crash This is an interesting bug since it is likely the cause of many other suspicious python crashes in blender. sys.last_traceback would store references to PyObjects at the point of the crash. it would only free these when sys.last_traceback was set again or on exit. This caused many crashes in the BGE while testing since python would end up freeing invalid game objects - When running scripts with errors, Blender would crash every 2-5 runs - in my test just now it crashed after 4 trys. It could also segfault blender, when (for eg) you run a script that has objects referenced. then load a new file and run another script that raises an error. In this case all the invalid Blender-Object's user counts would be decremented, even though none of the pointers were still valid. --- source/blender/python/BPY_interface.c | 9 ++++++++- .../gameengine/GameLogic/SCA_PythonController.cpp | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c index 29ef6c5da1d..dfcf6aa35a5 100644 --- a/source/blender/python/BPY_interface.c +++ b/source/blender/python/BPY_interface.c @@ -616,7 +616,12 @@ static void BPY_Err_Handle( char *script_name ) } Py_DECREF( tb ); } - + + /* Added in 2.48a, the last_traceback can reference Objects for example, increasing + * their user count. Not to mention holding references to wrapped data. + * This is especially bad when the PyObject for the wrapped data is free'd, after blender + * has alredy dealocated the pointer */ + PySys_SetObject( "last_traceback", Py_None); return; } @@ -2727,6 +2732,8 @@ int BPY_call_importloader( char *name ) * Description: This function executes the python script passed by text. * The Python dictionary containing global variables needs to * be passed in globaldict. +* NOTE: Make sure BPY_Err_Handle() runs if this returns NULL +* otherwise pointers can be left in sys.last_traceback that become invalid. *****************************************************************************/ static PyObject *RunPython( Text * text, PyObject * globaldict ) { diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index 4cb9bc8fe53..1bbb93e0acc 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -262,6 +262,13 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) printf("Python compile error from controller \"%s\": \n", GetName().Ptr()); //PyRun_SimpleString(m_scriptText.Ptr()); PyErr_Print(); + + /* Added in 2.48a, the last_traceback can reference Objects for example, increasing + * their user count. Not to mention holding references to wrapped data. + * This is especially bad when the PyObject for the wrapped data is free'd, after blender + * has alredy dealocated the pointer */ + PySys_SetObject( "last_traceback", Py_None); + return; } m_bModified=false; @@ -298,6 +305,13 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) // something is wrong, tell the user what went wrong printf("Python script error from controller \"%s\": \n", GetName().Ptr()); PyErr_Print(); + + /* Added in 2.48a, the last_traceback can reference Objects for example, increasing + * their user count. Not to mention holding references to wrapped data. + * This is especially bad when the PyObject for the wrapped data is free'd, after blender + * has alredy dealocated the pointer */ + PySys_SetObject( "last_traceback", Py_None); + //PyRun_SimpleString(m_scriptText.Ptr()); }