mirror of https://github.com/python/cpython
gh-118331: Don't raise an error if tuple allocation fails when clearing weakrefs (#118338)
It's not safe to raise an exception in `PyObject_ClearWeakRefs()` if one is not already set, since it may be called by `_Py_Dealloc()`, which requires that the active exception does not change. Additionally, make sure we clear the weakrefs even when tuple allocation fails.
This commit is contained in:
parent
444ac0b7a6
commit
43fa76638f
|
@ -10,6 +10,7 @@ import copy
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import random
|
import random
|
||||||
|
import textwrap
|
||||||
|
|
||||||
from test import support
|
from test import support
|
||||||
from test.support import script_helper, ALWAYS_EQ
|
from test.support import script_helper, ALWAYS_EQ
|
||||||
|
@ -1009,6 +1010,31 @@ class ReferencesTestCase(TestBase):
|
||||||
del x
|
del x
|
||||||
support.gc_collect()
|
support.gc_collect()
|
||||||
|
|
||||||
|
@support.cpython_only
|
||||||
|
def test_no_memory_when_clearing(self):
|
||||||
|
# gh-118331: Make sure we do not raise an exception from the destructor
|
||||||
|
# when clearing weakrefs if allocating the intermediate tuple fails.
|
||||||
|
code = textwrap.dedent("""
|
||||||
|
import _testcapi
|
||||||
|
import weakref
|
||||||
|
|
||||||
|
class TestObj:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def callback(obj):
|
||||||
|
pass
|
||||||
|
|
||||||
|
obj = TestObj()
|
||||||
|
# The choice of 50 is arbitrary, but must be large enough to ensure
|
||||||
|
# the allocation won't be serviced by the free list.
|
||||||
|
wrs = [weakref.ref(obj, callback) for _ in range(50)]
|
||||||
|
_testcapi.set_nomemory(0)
|
||||||
|
del obj
|
||||||
|
""").strip()
|
||||||
|
res, _ = script_helper.run_python_until_end("-c", code)
|
||||||
|
stderr = res.err.decode("ascii", "backslashreplace")
|
||||||
|
self.assertNotRegex(stderr, "_Py_Dealloc: Deallocator of type 'TestObj'")
|
||||||
|
|
||||||
|
|
||||||
class SubclassableWeakrefTestCase(TestBase):
|
class SubclassableWeakrefTestCase(TestBase):
|
||||||
|
|
||||||
|
|
|
@ -1016,7 +1016,9 @@ PyObject_ClearWeakRefs(PyObject *object)
|
||||||
PyObject *exc = PyErr_GetRaisedException();
|
PyObject *exc = PyErr_GetRaisedException();
|
||||||
PyObject *tuple = PyTuple_New(num_weakrefs * 2);
|
PyObject *tuple = PyTuple_New(num_weakrefs * 2);
|
||||||
if (tuple == NULL) {
|
if (tuple == NULL) {
|
||||||
_PyErr_ChainExceptions1(exc);
|
_PyWeakref_ClearWeakRefsExceptCallbacks(object);
|
||||||
|
PyErr_WriteUnraisable(NULL);
|
||||||
|
PyErr_SetRaisedException(exc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue