Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion Failing GC assertion when defining extension types with weakref support
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Jean-Paul Calderone  
View profile  
 More options Oct 11 2012, 9:21 am
From: Jean-Paul Calderone <calderone.jeanp...@gmail.com>
Date: Thu, 11 Oct 2012 06:21:44 -0700 (PDT)
Local: Thurs, Oct 11 2012 9:21 am
Subject: Re: [cython-users] Failing GC assertion when defining extension types with weakref support

On Thursday, October 11, 2012 2:44:15 AM UTC-4, Stefan Behnel wrote:

> You are accessing a Python object attribute in __dealloc__(). Python's
> garbage collector is free to clear Python object attributes at any moment
> between the time the last reachable reference to an object dies and the
> time the object is cleaned up and __dealloc__() is called. This definitely
> happens when a reference cycle is involved, because in order to clean it
> up, the garbage collector must start by killing a reference somewhere in
> order to break the cycle, so it takes an arbitrary object and sets its
> object attributes to None. The code above will stop working and do nothing
> in that case because self.objects is None, i.e. False.

Indeed.  I forgot about that while minimizing the example.  This doesn't
affect my actual code, I think, as the "list of objects" is actually held
inside the c++ object pointed to by self.thisptr - and I think that
self.thisptr is safe in __dealloc__?

I dug a little more and came across something I don't understand in the
handling of __weakref__ in the generated tp_traverse for this type.

    e = (*v)(o->__weakref__, a); if (e) return e;

Based on inspection of some types defined by CPython itself (eg the ones in
Modules/_io/fileio.c), this looks fishy.  The CPython documentation for
what to do with the __weakref__ list is rather absent unfortunately, so I'm
not *sure* this is wrong.  However, changing the Cython code generator to
omit this particular traversal gets rid of the failing gc assertion
(replacing it with another failing assertion about a negative reference
count - which doesn't do anything for my confidence about the *correctness*
of this change).  I also talked to Yhg1s on #python and his understanding
is that it is not the type's responsibility to traverse this list - it is
owned by the weak reference system, not the instance.  The resulting double
traversal seems consistent with the failing assertion in my initial post.

I've also filed this bug against CPython about the poor documentation:
http://bugs.python.org/issue16195

Perhaps it will result in some more clarity on the issue.

As I mentioned, the example still doesn't work.  The next failure after
changing the code generator is:

Fatal Python error: bullet/bullet.cpp:724 object at 0x1aa9a58 has negative
ref count -1

I wonder if this is due to the casts in the example doing the wrong thing.
 Does `<object>integer` actually give me the PyObject* with the address
`integer`?  Or is it a no-op, since Python integers are indeed already
objects (resulting in the Py_DECREF applying to the wrong object).  If so,
I wonder how to spell the correct cast.

Thanks,
Jean-Paul



 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.