On Monday, December 31, 2012 4:09:47 PM UTC+1, Jean-Pierre Flori wrote:
>
>
>
> On Monday, December 31, 2012 12:12:52 AM UTC+1, Nils Bruin wrote:
>>
>> OK, caught redhanded. Indeed, the freelist of this pool ends up being 
>> circular, due to a double free happening. The first free is 
>> indeed coming from a TripleDictEraser callback. The second one doesn't 
>> seem to be. Indeed, the second one doesn't seem to be 
>> triggered by a GC, but simply by a refcount hitting zero. Either that 
>> or someone holding a pointer to an object on which it blindly 
>> calls a release. I imagine that could happen in an extension class 
>> where object pointers are stored in c variables. Objects that get 
>> cleaned up as circular garbage can't trust that everything they're 
>> used to pointing at is still alive during a dealloc. Perhaps 
>> __pyx_tp_dealloc_4sage_9structure_15category_object_CategoryObject 
>> needs to be examined for how it clears its substructures. Once 
>> circular references are involved (or hidden ones as with weakrefs) the 
>> rug can really be pulled from under you. 
>>
>> tracebacks below 
>>
>> (here 0x7fffbeb3e008 == &(pool->freeblock) ) 
>>
>> (gdb) p *(block **) 0x7fffbeb3e008 
>> (gdb) p *(block **) 0x7fffbeb3e008 
>> $9 = (block *) 0x7fffbeb3e330 "0\u4cfe\377\177" 
>> (gdb) p *(block **) 0x7fffbeb3e330 
>> $10 = (block *) 0x7fffbeb3e430 "" 
>> (gdb) p *(block **) 0x7fffbeb3e430 
>>
>> traceback is: 
>>
>> #0  PyObject_Free (p=0x7fffbeb3e330) at Objects/obmalloc.c:981 
>> #1  0x00007ffff7cc7b76 in subtype_dealloc (self=0x7fffbeb3e350) at 
>> Objects/typeobject.c:1014 
>> #2  0x00007ffff7d4b7ca in delete_garbage (old=0x7ffff7fe19e0, 
>> collectable=0x7fffffffafb0) at Modules/gcmodule.c:770 
>> #3  collect (generation=1) at Modules/gcmodule.c:930 
>> #4  0x00007ffff7d4c1a8 in collect_generations () at Modules/gcmodule.c: 
>> 996 
>> #5  _PyObject_GC_Malloc (basicsize=<optimized out>) at Modules/ 
>> gcmodule.c:1457 
>> #6  _PyObject_GC_Malloc (basicsize=<optimized out>) at Modules/ 
>> gcmodule.c:1439 
>> #7  0x00007ffff7d4c1cd in _PyObject_GC_New (tp=0x7ffff7fb7d00) at 
>> Modules/gcmodule.c:1467 
>> #8  0x00007ffff7c86cb8 in PyWrapper_New (d=0x7ffff7bce230, 
>> self=0xb2eca0) at Objects/descrobject.c:1068 
>> #9  0x00007ffff7cafcda in _PyObject_GenericGetAttrWithDict 
>> (obj=0xb2eca0, name=0x7ffff7bbc180, dict=0x0) at Objects/object.c:1434 
>> #10 0x00007fffe99685b9 in 
>> __pyx_pf_4sage_9structure_11coerce_dict_16TripleDictEraser_2__call__ 
>> (__pyx_v_r=<optimized out>, 
>>     __pyx_v_self=<optimized out>) at sage/structure/coerce_dict.c:1225 
>> #11 
>> __pyx_pw_4sage_9structure_11coerce_dict_16TripleDictEraser_3__call__ 
>> (__pyx_v_self=0x7fffea8659b8, 
>>     __pyx_args=<optimized out>, __pyx_kwds=<optimized out>) at sage/ 
>> structure/coerce_dict.c:966 
>> #12 0x00007ffff7c6f403 in PyObject_Call (func=0x7fffea8659b8, 
>> arg=<optimized out>, kw=<optimized out>) at Objects/abstract.c:2529 
>> #13 0x00007ffff7c6fcf0 in PyObject_CallFunctionObjArgs 
>> (callable=0x7fffea8659b8) at Objects/abstract.c:2760 
>> #14 0x00007ffff7cd7b0e in handle_callback (callback=0x7fffea8659b8, 
>> ref=0x7fffbeb520b0) at Objects/weakrefobject.c:881 
>> #15 PyObject_ClearWeakRefs (object=<optimized out>) at Objects/ 
>> weakrefobject.c:928 
>> #16 0x00007fffe9f9f0d0 in 
>> __pyx_tp_dealloc_4sage_9structure_15category_object_CategoryObject 
>> (o=0x7fffbeb3e350) 
>>     at sage/structure/category_object.c:8989 
>> #17 0x00007ffff7cc7b76 in subtype_dealloc (self=0x7fffbeb3e350) at 
>> Objects/typeobject.c:1014 
>>
>> A little later on: 
>>
>> (gdb) p *(block **) 0x7fffbeb3e008 
>> $24 = (block *) 0x7fffbeb3e330 "0\u3cfe\377\177" 
>> (gdb) p *(block **) 0x7fffbeb3e330 
>> $25 = (block *) 0x7fffbeb3e330 "0\u3cfe\377\177" 
>>
>> ///THIS IS BAD! This is a circular freelist. 
>>
>> traceback: 
>>
>> #0  PyObject_Free (p=0x7fffbeb3e330) at Objects/obmalloc.c:980 
>> #1  0x00007ffff7cc7b76 in subtype_dealloc (self=0x7fffbeb3e350) at 
>> Objects/typeobject.c:1014 
>> #2  0x00007ffff7ca7c97 in insertdict (mp=0x621180, key=0x7ffff7bc0b70, 
>> hash=12160036574, value=0x7ffff7fc6840) 
>>     at Objects/dictobject.c:530 
>> #3  0x00007ffff7caa3ce in PyDict_SetItem (op=0x621180, key=<optimized 
>> out>, value=0x7ffff7fc6840) at Objects/dictobject.c:775 
>> #4  0x00007ffff7caffcb in _PyObject_GenericSetAttrWithDict 
>> (obj=<optimized out>, name=0x7ffff7bc0b70, value=0x7ffff7fc6840, 
>>     dict=0x621180) at Objects/object.c:1524 
>> #5  0x00007ffff7caf9b7 in PyObject_SetAttr (v=0x7ffff7bbbad0, 
>> name=0x7ffff7bc0b70, value=0x7ffff7fc6840) at Objects/object.c:1247 
>> #6  0x00007ffff7d0f3d1 in PyEval_EvalFrameEx (f=<optimized out>, 
>> throwflag=<optimized out>) at Python/ceval.c:2004 
>> #7  0x00007ffff7d14275 in PyEval_EvalCodeEx (co=<optimized out>, 
>> globals=<optimized out>, locals=<optimized out>, 
>>     args=<optimized out>, argcount=1, kws=0x0, kwcount=0, defs=0x0, 
>> defcount=0, closure=0x0) at Python/ceval.c:3253 
>> #8  0x00007ffff7c9717c in function_call (func=0x7fffc14af1b8, 
>> arg=0x7fffbeb01190, kw=0x0) at Objects/funcobject.c:526 
>> #9  0x00007ffff7c6f403 in PyObject_Call (func=0x7fffc14af1b8, 
>> arg=<optimized out>, kw=<optimized out>) at Objects/abstract.c:2529 
>> #10 0x00007ffff7d0cc97 in PyEval_CallObjectWithKeywords 
>> (func=0x7fffc14af1b8, arg=0x7fffbeb01190, kw=<optimized out>) 
>>     at Python/ceval.c:3890 
>> #11 0x00007ffff7d11d12 in PyEval_EvalFrameEx (f=<optimized out>, 
>> throwflag=<optimized out>) at Python/ceval.c:1739 
>> #12 0x00007ffff7d14275 in PyEval_EvalCodeEx (co=<optimized out>, 
>> globals=<optimized out>, locals=<optimized out>, 
>>     args=<optimized out>, argcount=0, kws=0x0, kwcount=0, defs=0x0, 
>> defcount=0, closure=0x0) at Python/ceval.c:3253 
>> #13 0x00007ffff7d143b2 in PyEval_EvalCode (co=<optimized out>, 
>> globals=<optimized out>, locals=<optimized out>) 
>>     at Python/ceval.c:667 
>> #14 0x00007ffff7d123df in exec_statement (locals=0x2b65b60, 
>> globals=0x2b65b60, prog=<optimized out>, f=0x2809550) 
>>     at Python/ceval.c:4718 
>> #15 PyEval_EvalFrameEx (f=<optimized out>, throwflag=<optimized out>) 
>> at Python/ceval.c:1880 
>> #16 0x00007ffff7d14275 in PyEval_EvalCodeEx (co=<optimized out>, 
>> globals=<optimized out>, locals=<optimized out>, 
>>     args=<optimized out>, argcount=5, kws=0x0, kwcount=0, defs=0x0, 
>> defcount=0, closure=0x0) at Python/ceval.c:3253 
>>
> Not really sure but we might be interested in the Py_Clear macro to deal 
> with such intricated cases. 
>
In particular, http://docs.python.org/2/c-api/refcounting.html states:
"It is a good idea to use this macro whenever decrementing the value of a 
variable that might be traversed during garbage collection." 
Not sure if this is required though.

-- 
You received this message because you are subscribed to the Google Groups 
"sage-devel" group.
To post to this group, send email to sage-devel@googlegroups.com.
To unsubscribe from this group, send email to 
sage-devel+unsubscr...@googlegroups.com.
Visit this group at http://groups.google.com/group/sage-devel?hl=en.


Reply via email to