[Bf-committers] [Bf-blender-cvs] SVN commit: /data/svn/bf-blender [19724] trunk/blender/source: Fix for own recent reference count error.

Campbell Barton ideasman42 at gmail.com
Wed Apr 15 07:53:15 CEST 2009


Its a list of all armatures python currently has (as PyObject *'s).
When python runs Window.EditMode editmode it can rebuild the python
armatures editbone dictionary so the pointers are always valid.

Looking at this now and it should check if G.obedit is an armature
type, but I rather not touch this.

Even with this check its still very easy to crash blender when using
armature editbones.
The only way I could use armature editbones successfully was to keep
them local to one function so no references to EditBones weren't left
hanging around (in classes/ lists or just in the namespace).

 can only hope nobody tries to get this api in 2.5!
- Campbell

On Tue, Apr 14, 2009 at 10:35 PM, joe <joeedh at gmail.com> wrote:
> What is the armature weaklist, btw?  I never could figure that out.
>
> Joe
>
> On Tue, Apr 14, 2009 at 10:34 PM, Campbell Barton <ideasman42 at gmail.com> wrote:
>> Revision: 19724
>>          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=19724
>> Author:   campbellbarton
>> Date:     2009-04-15 06:34:27 +0200 (Wed, 15 Apr 2009)
>>
>> Log Message:
>> -----------
>> Fix for own recent reference count error.
>> - The armature weakref list was  being incref'd twice then decrefed twice (incref and decref were used incorrectly), now only once. My 'fix' broke this.
>> - In bpy_pydriver_create_dict the 2 refs added from running PyDict_SetItemString twice were undone when clearing the dictionary (added comment)
>> - changed Py_XDECREF to Py_DECREF int BPY_pyconstraint_update and BPY_pyconstraint_target, Py_XDECREF checs for NULL value which would have crashed blender before it got to Py_XDECREF anyway.
>> - after every error is reported (PyErr_Print), remove sys.last_traceback and clear the error, I found this fixed certain crashes (usually when starting the game engine or exiting blender), so best do this all the time.
>>
>> - header_text.c, CcdPhysicsEnvironment.cpp, KX_CameraActuator.cpp - remove some warnings.
>>
>> Modified Paths:
>> --------------
>>    trunk/blender/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c
>>    trunk/blender/source/blender/python/BPY_interface.c
>>    trunk/blender/source/blender/python/api2_2x/Draw.c
>>    trunk/blender/source/blender/python/api2_2x/bpy_internal_import.c
>>    trunk/blender/source/blender/src/header_text.c
>>    trunk/blender/source/blender/src/imagepaint.c
>>    trunk/blender/source/gameengine/GameLogic/SCA_PythonController.cpp
>>    trunk/blender/source/gameengine/Ketsji/KX_CameraActuator.cpp
>>    trunk/blender/source/gameengine/Ketsji/KX_PolygonMaterial.cpp
>>    trunk/blender/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
>>
>> Modified: trunk/blender/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c
>> ===================================================================
>> --- trunk/blender/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c   2009-04-15 03:22:22 UTC (rev 19723)
>> +++ trunk/blender/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c   2009-04-15 04:34:27 UTC (rev 19724)
>> @@ -340,7 +340,11 @@
>>        PyGILState_STATE gilstate = PyGILState_Ensure();
>>
>>        fprintf(stderr, "\nError in dynamic node script \"%s\":\n", node->name);
>> -       if (PyErr_Occurred()) { PyErr_Print(); }
>> +       if (PyErr_Occurred()) {
>> +               PyErr_Print();
>> +               PyErr_Clear();
>> +               PySys_SetObject("last_traceback", NULL);
>> +       }
>>        else { fprintf(stderr, "Not a valid dynamic node Python script.\n"); }
>>
>>        PyGILState_Release(gilstate);
>>
>> Modified: trunk/blender/source/blender/python/BPY_interface.c
>> ===================================================================
>> --- trunk/blender/source/blender/python/BPY_interface.c 2009-04-15 03:22:22 UTC (rev 19723)
>> +++ trunk/blender/source/blender/python/BPY_interface.c 2009-04-15 04:34:27 UTC (rev 19724)
>> @@ -97,6 +97,17 @@
>>  PyObject *bpy_orig_syspath_List = NULL;
>>
>>
>> +static void BPY_Err_Clear(void)
>> +{
>> +       /* 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", NULL);
>> +
>> +       PyErr_Clear();
>> +}
>> +
>>  /*
>>  * set up a weakref list for Armatures
>>  *    creates list in __main__ module dict
>> @@ -107,30 +118,29 @@
>>        PyObject *maindict;
>>        PyObject *main_module;
>>        PyObject *list;
>> -       char *list_name = ARM_WEAKREF_LIST_NAME;
>> +       PyObject *list_name = PyString_FromString(ARM_WEAKREF_LIST_NAME);
>>
>>        main_module = PyImport_AddModule( "__main__");
>>        if(main_module){
>> -               PyObject *weakreflink;
>>                maindict= PyModule_GetDict(main_module);
>>
>>                /* check if there is already a dict entry for the armature weakrefs,
>>                 * and delete if so before making another one */
>> -
>> -               weakreflink= PyDict_GetItemString(maindict,list_name);
>> -               if( weakreflink != NULL ) {
>> -                       PyDict_DelItemString(maindict,list_name);
>> -                       Py_XDECREF( weakreflink );
>> -               }
>>
>> +               if (PyDict_DelItem(maindict, list_name)==-1)
>> +                       PyErr_Clear();
>> +
>>                list= PyList_New(0);
>> -               if (PyDict_SetItemString(maindict, list_name, list) == -1){
>> -                       printf("Oops - setup_armature_weakrefs()\n");
>> +               if (PyDict_SetItem(maindict, list_name, list) == -1){
>> +                       PyErr_Print();
>> +                       BPY_Err_Clear();
>>                        Py_DECREF(list);
>> +                       Py_DECREF(list_name);
>>                        return 0;
>>                }
>>                Py_DECREF(list); /* the dict owns it now */
>>        }
>> +       Py_DECREF(list_name);
>>        return 1;
>>  }
>>
>> @@ -532,16 +542,6 @@
>>        else return PyString_FromString("unknown");
>>  }
>>
>> -static void BPY_Err_Clear(void)
>> -{
>> -       /* 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);
>> -
>> -       PyErr_Clear();
>> -}
>>  /****************************************************************************
>>  * Description: Blender Python error handler. This catches the error and
>>  * stores filename and line number in a global
>> @@ -1137,6 +1137,7 @@
>>
>>        if( PyErr_Occurred(  ) ) {      /* if script ended after filesel */
>>                PyErr_Print(  );        /* eventual errors are handled now */
>> +               BPY_Err_Clear(  );
>>                error_pyscript(  );
>>        }
>>
>> @@ -1245,10 +1246,9 @@
>>        if (mod) {
>>                PyDict_SetItemString(d, "Blender", mod);
>>                PyDict_SetItemString(d, "b", mod);
>> -               Py_DECREF(mod);
>> -               Py_DECREF(mod);
>> +               Py_DECREF(mod); /* 2 refs above are cleared with the dict, only decref the ref from PyImport_ImportModule */
>>        } else {
>> -               PyErr_Clear();
>> +               BPY_Err_Clear();
>>        }
>>
>>        mod = PyImport_ImportModule("math");
>> @@ -1258,18 +1258,18 @@
>>                /* Only keep for backwards compat! - just import all math into root, they are standard */
>>                PyDict_SetItemString(d, "math", mod);
>>                PyDict_SetItemString(d, "m", mod);
>> -               Py_DECREF(mod);
>> -               Py_DECREF(mod);
>> -       }
>> +               Py_DECREF(mod); /* 2 refs above are cleared with the dict, only decref the ref from PyImport_ImportModule */
>> +       } else {
>> +               BPY_Err_Clear();
>> +       }
>>
>>        mod = PyImport_ImportModule("Blender.Noise");
>>        if (mod) {
>>                PyDict_SetItemString(d, "noise", mod);
>>                PyDict_SetItemString(d, "n", mod);
>> -               Py_DECREF(mod);
>> -               Py_DECREF(mod);
>> +               Py_DECREF(mod); /* 2 refs above are cleared with the dict, only decref the ref from PyImport_ImportModule */
>>        } else {
>> -               PyErr_Clear();
>> +               BPY_Err_Clear();
>>        }
>>
>>        /* If there's a Blender text called pydrivers.py, import it.
>> @@ -1279,10 +1279,9 @@
>>                if (mod) {
>>                        PyDict_SetItemString(d, "pydrivers", mod);
>>                        PyDict_SetItemString(d, "p", mod);
>> -                       Py_DECREF(mod);
>> -                       Py_DECREF(mod);
>> +                       Py_DECREF(mod); /* 2 refs above are cleared with the dict, only decref the ref from PyImport_ImportModule */
>>                } else {
>> -                       PyErr_Clear();
>> +                       BPY_Err_Clear();
>>                }
>>        }
>>        /* short aliases for some Get() functions: */
>> @@ -1297,7 +1296,7 @@
>>                        Py_DECREF(fcn);
>>                }
>>        } else {
>> -               PyErr_Clear();
>> +               BPY_Err_Clear();
>>        }
>>
>>        /* TODO - change these */
>> @@ -1311,7 +1310,7 @@
>>                        Py_DECREF(fcn);
>>                }
>>        } else {
>> -               PyErr_Clear();
>> +               BPY_Err_Clear();
>>        }
>>
>>        /* ma(matname) == Blender.Material.Get(matname) */
>> @@ -1324,7 +1323,7 @@
>>                        Py_DECREF(fcn);
>>                }
>>        } else {
>> -               PyErr_Clear();
>> +               BPY_Err_Clear();
>>        }
>>
>>        return 0;
>> @@ -1350,6 +1349,7 @@
>>                fprintf(stderr, "\nError in Ipo Driver: No Object\nThis is the failed Python expression:\n'%s'\n\n", driver->name);
>>
>>        PyErr_Print();
>> +       BPY_Err_Clear();
>>
>>        return 0.0f;
>>  }
>> @@ -1445,7 +1445,7 @@
>>                        return;
>>                }
>>
>> -               Py_XDECREF(retval);
>> +               Py_DECREF(retval);
>>                retval = NULL;
>>
>>                /* try to find NUM_TARGETS */
>> @@ -1578,9 +1578,9 @@
>>                con->flag |= PYCON_SCRIPTERROR;
>>
>>                /* free temp objects */
>> -               Py_XDECREF(idprop);
>> -               Py_XDECREF(srcmat);
>> -               Py_XDECREF(tarmats);
>> +               Py_DECREF(idprop);
>> +               Py_DECREF(srcmat);
>> +               Py_DECREF(tarmats);
>>
>>                ReleaseGlobalDictionary(globals);
>>
>> @@ -1589,7 +1589,7 @@
>>                return;
>>        }
>>
>> -       if (retval) {Py_XDECREF( retval );}
>> +       Py_DECREF( retval );
>>        retval = NULL;
>>
>>        gval = PyDict_GetItemString(globals, "doConstraint");
>> @@ -1597,9 +1597,9 @@
>>                printf("ERROR: no doConstraint function in constraint!\n");
>>
>>                /* free temp objects */
>> -               Py_XDECREF(idprop);
>> -               Py_XDECREF(srcmat);
>> -               Py_XDECREF(tarmats);
>> +               Py_DECREF(idprop);
>> +               Py_DECREF(srcmat);
>> +               Py_DECREF(tarmats);
>>
>>                ReleaseGlobalDictionary(globals);
>>
>> @@ -1612,15 +1612,15 @@
>>        if (PyFunction_Check(gval)) {
>>                pyargs = Py_BuildValue("OOO", srcmat, tarmats, idprop);
>>                retval = PyObject_CallObject(gval, pyargs);
>> -               Py_XDECREF(pyargs);
>> +               Py_DECREF(pyargs);
>>        }
>>        else {
>>                printf("ERROR: doConstraint is supposed to be a function!\n");
>>                con->flag |= PYCON_SCRIPTERROR;
>>
>> -               Py_XDECREF(idprop);
>> -               Py_XDECREF(srcmat);
>> -               Py_XDECREF(tarmats);
>> +               Py_DECREF(idprop);
>> +               Py_DECREF(srcmat);
>> +               Py_DECREF(tarmats);
>>
>>                ReleaseGlobalDictionary(globals);
>>
>> @@ -1634,9 +1634,9 @@
>>                con->flag |= PYCON_SCRIPTERROR;
>>
>>                /* free temp objects */
>> -               Py_XDECREF(idprop);
>> -               Py_XDECREF(srcmat);
>> -               Py_XDECREF(tarmats);
>> +               Py_DECREF(idprop);
>> +               Py_DECREF(srcmat);
>> +               Py_DECREF(tarmats);
>>
>>                ReleaseGlobalDictionary(globals);
>>
>> @@ -1650,10 +1650,10 @@
>>                printf("Error in PyConstraint - doConstraint: Function not returning a matrix!\n");
>>                con->flag |= PYCON_SCRIPTERROR;
>>
>> -               Py_XDECREF(idprop);
>> -               Py_XDECREF(srcmat);
>> -               Py_XDECREF(tarmats);
>> -               Py_XDECREF(retval);
>> +               Py_DECREF(idprop);
>> +               Py_DECREF(srcmat);
>> +               Py_DECREF(tarmats);
>> +               Py_DECREF(retval);
>>
>>                ReleaseGlobalDictionary(globals);
>>
>> @@ -1667,10 +1667,10 @@
>>                printf("Error in PyConstraint - doConstraint: Matrix returned is the wrong size!\n");
>>                con->flag |= PYCON_SCRIPTERROR;
>>
>> -               Py_XDECREF(idprop);
>> -               Py_XDECREF(srcmat);
>> -               Py_XDECREF(tarmats);
>> -               Py_XDECREF(retval);
>> +               Py_DECREF(idprop);
>> +               Py_DECREF(srcmat);
>> +               Py_DECREF(tarmats);
>> +               Py_DECREF(retval);
>>
>>                ReleaseGlobalDictionary(globals);
>>
>> @@ -1687,10 +1687,10 @@
>>        }
>>
>>        /* free temp objects */
>> -       Py_XDECREF(idprop);
>> -       Py_XDECREF(srcmat);
>> -       Py_XDECREF(tarmats);
>> -       Py_XDECREF(retval);
>> +       Py_DECREF(idprop);
>> +       Py_DECREF(srcmat);
>> +       Py_DECREF(tarmats);
>> +       Py_DECREF(retval);
>>
>>        /* clear globals */
>>        ReleaseGlobalDictionary(globals);
>> @@ -1745,10 +1745,10 @@
>>                con->flag |= PYCON_SCRIPTERROR;
>>
>>                /* free temp objects */
>> -               Py_XDECREF(tar);
>> -               Py_XDECREF(subtar);
>> -               Py_XDECREF(idprop);
>> -               Py_XDECREF(tarmat);
>> +               Py_DECREF(tar);
>> +               Py_DECREF(subtar);
>> +               Py_DECREF(idprop);
>> +               Py_DECREF(tarmat);
>>
>>                ReleaseGlobalDictionary(globals);
>>
>> @@ -1757,17 +1757,17 @@
>>                return;
>>        }
>>
>> -       Py_XDECREF(retval);
>> +       Py_DECREF(retval);
>>        retval = NULL;
>>
>>        /* try to find doTarget function to set the target matrix */
>>        gval = PyDict_GetItemString(globals, "doTarget");
>>        if (!gval) {
>>                /* free temp objects */
>> -               Py_XDECREF(tar);
>> -               Py_XDECREF(subtar);
>> -               Py_XDECREF(idprop);
>> -               Py_XDECREF(tarmat);
>> +               Py_DECREF(tar);
>> +               Py_DECREF(subtar);
>> +               Py_DECREF(idprop);
>> +               Py_DECREF(tarmat);
>>
>>                ReleaseGlobalDictionary(globals);
>>
>> @@ -1780,16 +1780,16 @@
>>        if (PyFunction_Check(gval)) {
>>                pyargs = Py_BuildValue("OOOO", tar, subtar, tarmat, idprop);
>>                retval = PyObject_CallObject(gval, pyargs);
>> -               Py_XDECREF(pyargs);
>> +               Py_DECREF(pyargs);
>>        }
>>        else {
>>                printf("ERROR: doTarget is supposed to be a function!\n");
>>                con->flag |= PYCON_SCRIPTERROR;
>>
>> -               Py_XDECREF(tar);
>> -               Py_XDECREF(subtar);
>> -               Py_XDECREF(idprop);
>> -               Py_XDECREF(tarmat);
>> +               Py_DECREF(tar);
>> +               Py_DECREF(subtar);
>> +               Py_DECREF(idprop);
>> +               Py_DECREF(tarmat);
>>
>>                ReleaseGlobalDictionary(globals);
>>
>> @@ -1804,10 +1804,10 @@
>>
>>
>>                /* free temp objects */
>> -               Py_XDECREF(tar);
>> -               Py_XDECREF(subtar);
>> -               Py_XDECREF(idprop);
>> -               Py_XDECREF(tarmat);
>> +               Py_DECREF(tar);
>> +               Py_DECREF(subtar);
>> +               Py_DECREF(idprop);
>> +               Py_DECREF(tarmat);
>>
>>                ReleaseGlobalDictionary(globals);
>>
>> @@ -1819,11 +1819,11 @@
>>        if (!PyObject_TypeCheck(retval, &matrix_Type)) {
>>                con->flag |= PYCON_SCRIPTERROR;
>>
>> -               Py_XDECREF(tar);
>> -               Py_XDECREF(subtar);
>> -               Py_XDECREF(idprop);
>> -               Py_XDECREF(tarmat);
>> -               Py_XDECREF(retval);
>> +               Py_DECREF(tar);
>> +               Py_DECREF(subtar);
>> +               Py_DECREF(idprop);
>> +               Py_DECREF(tarmat);
>> +               Py_DECREF(retval);
>>
>>                ReleaseGlobalDictionary(globals);
>>
>> @@ -1837,11 +1837,11 @@
>>                printf("Error in PyConstraint - doTarget: Matrix returned is the wrong size!\n");
>>                con->flag |= PYCON_SCRIPTERROR;
>>
>> -               Py_XDECREF(tar);
>> -               Py_XDECREF(subtar);
>>
>> @@ Diff output truncated at 10240 characters. @@
>>
>> _______________________________________________
>> Bf-blender-cvs mailing list
>> Bf-blender-cvs at blender.org
>> http://lists.blender.org/mailman/listinfo/bf-blender-cvs
>>
> _______________________________________________
> Bf-committers mailing list
> Bf-committers at blender.org
> http://lists.blender.org/mailman/listinfo/bf-committers
>


More information about the Bf-committers mailing list