fix for [#17878] Scripts operating on blender objects don't clear memory after a...
authorCampbell Barton <ideasman42@gmail.com>
Wed, 22 Oct 2008 03:10:00 +0000 (03:10 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Wed, 22 Oct 2008 03:10:00 +0000 (03:10 +0000)
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
source/gameengine/GameLogic/SCA_PythonController.cpp

index 29ef6c5da1d28ea371231857bca7931773294887..dfcf6aa35a5d2fb4e1b042c24ff12739c565cd4b 100644 (file)
@@ -616,7 +616,12 @@ static void BPY_Err_Handle( char *script_name )
                }
                Py_DECREF( tb );
        }
                }
                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;
 }
 
        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.
 * 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 )
 {
 *****************************************************************************/
 static PyObject *RunPython( Text * text, PyObject * globaldict )
 {
index 4cb9bc8fe530d025c8fb4e7d4c702b8a80822536..1bbb93e0acc9c107b563ab43fcdc4f795a4e84ae 100644 (file)
@@ -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();
                        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;
                        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();
                // 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());
        }
 
                //PyRun_SimpleString(m_scriptText.Ptr());
        }