My guess is that ZODB data structures are lying around with fields
that Python 2.7 recognizes as pointers, but which haven't increased
the refcount. Thus, if GC examines them it may find more pointers than
explained by the refcount ... ERROR! These objects are just lying on
the python heap. It's a matter of chance whether a GC gets triggered
that stumbles into them. What you SHOULD do is investigate on what
object the assertion fails. That's how I found BTree to be implicated.
Its implication has nothing to do with what code actually gets
executed (other than triggering the right kind of garbage
collection).
Note that with "print ..." you can basically execute arbitrary C
instructions in gdb, which means you have the entire Python library at
your disposal. Of course, executing these routines will foul up the
heap even further, so don't expect this to go very far, but examining
the string representation of one or two objects on the stack should be
doable with a bit of luck.
I'm pretty sure we have to upgrade ZODB. The linked bugreport upstairs
declares "python 2.7 will be unsupported unless we have a
breakthrough", and luckily they did have a breakthrough, so 3.10 does
support 2.7.
ZODB is just a database that gets used (and several instances
initialized at startup!) by sage.