Skip to content

Commit 051b168

Browse files
authored
gh-157242: Fix set_nomemory() on Py_TRACE_REFS build (#157351)
On Py_TRACE_REFS build, use malloc() and free() functions of the C library for the "reference chain" hash table. So it becomes possible to use _testcapi.set_nomemory() with Py_TRACE_REFS. Mark new tests using set_nomemory() with @support.nomemtest.
1 parent 67e6be7 commit 051b168

4 files changed

Lines changed: 13 additions & 13 deletions

File tree

Lib/test/support/__init__.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1364,21 +1364,16 @@ def wrapper(self):
13641364
return wrapper
13651365
return decorator
13661366

1367-
def nomemtest(f):
1367+
def nomemtest(test):
13681368
"""Check that we can use this test with `_testcapi.set_nomemory`."""
13691369
from .import_helper import import_module
13701370

1371-
@functools.wraps(f)
1371+
@functools.wraps(test)
13721372
def internal(*args, **kwargs):
13731373
import_module('_testcapi')
1374-
return f(*args, **kwargs)
1374+
return test(*args, **kwargs)
13751375

1376-
return unittest.skipIf(
1377-
# Python built with Py_TRACE_REFS fail with a fatal error in
1378-
# _PyRefchain_Trace() on memory allocation error.
1379-
Py_TRACE_REFS,
1380-
'cannot test Py_TRACE_REFS build',
1381-
)(cpython_only(internal))
1376+
return cpython_only(internal)
13821377

13831378
def bigaddrspacetest(f):
13841379
"""Decorator for tests that fill the address space."""

Lib/test/test_bytes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1569,6 +1569,7 @@ def test_resize(self):
15691569
self.assertRaises(MemoryError, bytearray().resize, sys.maxsize)
15701570
self.assertRaises(MemoryError, bytearray(1000).resize, sys.maxsize)
15711571

1572+
@support.nomemtest
15721573
def test_resize_error(self):
15731574
# gh-157242: If bytearray.resize() fails (MemoryError),
15741575
# the bytearray must be left unchanged.
@@ -1662,6 +1663,7 @@ def test_take_bytes(self):
16621663
self.assertEqual(ba, bytearray(b'A'))
16631664
self.assertEqual(ord(b'c'), ord('c'))
16641665

1666+
@support.nomemtest
16651667
def test_take_bytes_error(self):
16661668
# gh-157242: If bytearray.take_bytes() fails (MemoryError),
16671669
# the bytearray must be left unchanged.

Lib/test/test_capi/test_bytes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import sys
22
import unittest
3+
from test import support
34
from test.support import import_helper
45

56
_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
@@ -389,6 +390,7 @@ def test_resize(self):
389390
writer.resize(len(b'number=123456'), b'456')
390391
self.assertEqual(writer.finish(), self.result_type(b'number=123456'))
391392

393+
@support.nomemtest
392394
def test_resize_error(self):
393395
small_buffer = _testcapi.PyBytesWriter_small_buffer
394396
init = b'x' * (small_buffer * 2)

Objects/object.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,10 +198,11 @@ refchain_init(PyInterpreterState *interp)
198198
return 0;
199199
}
200200
_Py_hashtable_allocator_t alloc = {
201-
// Don't use default PyMem_Malloc() and PyMem_Free() which
202-
// require the caller to hold the GIL.
203-
.malloc = PyMem_RawMalloc,
204-
.free = PyMem_RawFree,
201+
// Use directly malloc() and free() of the C library. Using
202+
// PyMem_RawMalloc() and PyMem_RawFree() prevents testing
203+
// _testcapi.set_nomemory().
204+
.malloc = malloc,
205+
.free = free,
205206
};
206207
REFCHAIN(interp) = _Py_hashtable_new_full(
207208
_Py_hashtable_hash_ptr, _Py_hashtable_compare_direct,

0 commit comments

Comments
 (0)