Calling gc.collect() twice works around the issue, which sounds like a missing traverse function somewhere.
diff --git a/Python/pystate.c b/Python/pystate.c
index c791b23999..66bbe1bf7d 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -321,6 +321,7 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate)
/* Last garbage collection on this interpreter */
_PyGC_CollectNoFail(tstate);
+ _PyGC_CollectNoFail(tstate);
_PyGC_Fini(tstate);
/* We don't clear sysdict and builtins until the end of this function.