@@ -1554,18 +1554,14 @@ finalize_remove_modules(PyObject *modules, int verbose)
15541554 if (weaklist != NULL) { \
15551555 PyObject *wr = PyWeakref_NewRef(mod, NULL); \
15561556 if (wr) { \
1557- PyObject *tup; \
15581557 if (Py_REFCNT(wr) > 1) { \
1559- /* gh-132413: When the weakref is already used
1560- * elsewhere, keep the referenced module alive
1561- * until finalize_modules_clear_weaklist() finishes.
1562- */ \
1563- Py_INCREF (mod ); \
1564- tup = PyTuple_Pack (3 , name , wr , Py_True ); \
1565- } \
1566- else { \
1567- tup = PyTuple_Pack (3 , name , wr , Py_False ); \
1558+ /* gh-132413: When the weakref is already used elsewhere,
1559+ * finalize_modules_clear_weaklist() rather than the GC
1560+ * should clear the referenced module since the GC tries
1561+ * to clear the wrakref first. */ \
1562+ _PyObject_GC_UNTRACK (mod ); \
15681563 } \
1564+ PyObject * tup = PyTuple_Pack (2 , name , wr ); \
15691565 if (!tup || PyList_Append (weaklist , tup ) < 0 ) { \
15701566 PyErr_FormatUnraisable ("Exception ignored while removing modules" ); \
15711567 } \
@@ -1668,6 +1664,9 @@ finalize_modules_clear_weaklist(PyInterpreterState *interp,
16681664 continue ;
16691665 }
16701666 assert (PyModule_Check (mod ));
1667+ if (!_PyObject_GC_IS_TRACKED (mod )) {
1668+ _PyObject_GC_TRACK (mod );
1669+ }
16711670 PyObject * dict = _PyModule_GetDict (mod ); // borrowed reference
16721671 if (dict == interp -> builtins || dict == interp -> sysdict ) {
16731672 Py_DECREF (mod );
@@ -1678,9 +1677,6 @@ finalize_modules_clear_weaklist(PyInterpreterState *interp,
16781677 }
16791678 _PyModule_Clear (mod );
16801679 Py_DECREF (mod );
1681- if (PyTuple_GET_ITEM (tup , 2 ) == Py_True ) {
1682- Py_DECREF (mod );
1683- }
16841680 }
16851681}
16861682
0 commit comments