[Python-Dev] PyWeakref_GetObject() borrows its reference from... whom?

Larry Hastings larry at hastings.org
Mon Oct 10 17:14:02 EDT 2016


On 10/10/2016 09:36 PM, Chris Angelico wrote:
> Hmm. Here's a naughty, and maybe dangerous, theory. Obtain a "memory
> deallocation lock". While it is held (by any thread - it's a guard,
> more than a lock), Py_DECREF will not actually deallocate memory -
> objects can fall to zero references without being wiped. Once the
> lock/guard is freed/cleared, anything that had fallen to zero is now
> deallocated. This probably would mean stuffing them onto a list of
> "doomed objects", and upon release of the guard, any doomed objects
> that still have no refs would get deallocated.

If this worked, this would actually be really easy with my current 
"buffered reference counting" approach.  I literally already have a list 
of doomed objects, which a separate thread queues up for each thread to 
process later.

(This was a necessary part of "buffered reference counting", in which 
reference count changes are stored in a transaction log and later 
committed by a single thread.  Since there's only one thread making 
reference count changes, there's no contention, so it doesn't have to 
use atomic incr/decr, which is a big performance win.)

But I don't think this fixes the problem.  Consider:

 1. Thread A calls Q = PyList_GetItem(L, 0), which returns a borrowed
    reference.  Thread A then gets suspended, before it has a chance to
    Py_INCREF(Q).
 2. Thread B does L.clear(), the reference count of Q goes to 0, Q is
    added to the doomed objects list.
 3. Thread A gets to run again.  It does Py_INCREF(Q); Q's refcount is
    now back up to 1, as if Q had been resurrected.
 4. At some point in the future the "memory deallocation lock" is
    released and Q is deleted.

If you say "well, just look at the reference count, and if it's 1 throw 
it off the doomed objects list", keep in mind that I no longer have 
accurate real-time reference counts.  These hacks where we play games 
with the reference count are mostly removed in my branch.

Also, I don't know when it would ever be safe to release the "memory 
deallocation lock".  Just because it's safe for your thread doesn't mean 
it's safe for another thread.  And if you do it on a thread-by-thread 
basis, in the above example it might be safe from thread B's perspective 
to release its "memory deallocation lock", but as illustrated that can 
have an effect on thread A.

I appreciate the brainstorming but I'm not currently sanguine about this 
idea,


//arry/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20161010/3b343b29/attachment.html>


More information about the Python-Dev mailing list