gh-118331: Don't raise an error if tuple allocation fails when clearing weakrefs by mpage · Pull Request #118338 · python/cpython
It's not safe to raise an exception in PyObject_ClearWeakRefs() if one is not already set. PyObject_ClearWeakRefs() may be called (transitively) by _Py_Dealloc(), which contains
| // gh-89373: The tp_dealloc function must leave the current exception | |
| // unchanged. | |
| if (tstate != NULL && tstate->current_exception != old_exc) { | |
| const char *err; | |
| if (old_exc == NULL) { | |
| err = "Deallocator of type '%s' raised an exception"; | |
| } | |
| else if (tstate->current_exception == NULL) { | |
| err = "Deallocator of type '%s' cleared the current exception"; | |
| } | |
| else { | |
| // It can happen if dealloc() normalized the current exception. | |
| // A deallocator function must not change the current exception, | |
| // not even normalize it. | |
| err = "Deallocator of type '%s' overrode the current exception"; | |
| } | |
| _Py_FatalErrorFormat(__func__, err, type->tp_name); | |
| } |
Additionally, make sure we clear the weakrefs when tuple allocation fails.
This bug predates gh-111926. It exists in 3.12 and likely in earlier versions too. If it's getting tickled now, I suspect it's because we always allocate a tuple now when clearing weakrefs that have callbacks, whereas previously we only did so if there was more than one weakref with a callback, making it more likely that we fail to allocate a tuple when running test_repl.TestInteractiveInterpreter.test_no_memory.