[Tim] ...
The meaning of "clearing a weakref" has become ambiguous -- so far, to me (and I believe to Fred too) it's always meant both "set wr_object to Py_None" and "remove the weakref from its referent's list of weakrefs". You're sometimes using it to mean only the former. That may be a clever thing to do -- unsure yet.
It has one downside that seems rare (the full Zope3 test suite provokes it, but not Python's): say a weakref W "is cleared" just by setting wr_object to Py_None. If W's refcount later falls to 0, weakref_dealloc() won't remove W from W's referent's list of weakrefs. That's the way clear_weakref() is written, and I think it has to be that way: if clear_weakref doesn't know what the referent is, it can't find the pointer to the head of the referent's weakref list, so it can't unlink W from the list correctly (unlike gc's doubly-linked lists, weakref lists aren't circular, and don't have list heads) This leaves free'd memory *in* the referent's weakref list. So if the referent's refcount falls to 0 after that, then PyObject_ClearWeakRefs() goes nuts trying to crawl over the freed memory. In a debug build that's obvious when it happens, because _PyWeakref_GetWeakrefCount() hits a weakref object full of 0xdb bytes.