Skip to content

Commit e0827a5

Browse files
committed
much better
1 parent 78cac86 commit e0827a5

File tree

2 files changed

+23
-106
lines changed

2 files changed

+23
-106
lines changed

Lib/test/test_capi/test_misc.py

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2886,25 +2886,19 @@ def test_pack_version_ctypes(self):
28862886

28872887
class TestCEval(unittest.TestCase):
28882888
def test_ceval_decref(self):
2889-
def f():
2890-
l = []
2891-
del l
2892-
2893-
def g():
2894-
l = [], []
2895-
del l
2896-
2897-
_testcapi.toggle_reftrace_counter()
2898-
f()
2899-
refs = _testcapi.toggle_reftrace_counter()
2900-
# sometimes we get a stray DECREF from somewhere else (other thread?)
2901-
# doesn't happen outside of test
2902-
self.assertIn(refs, ((1, 1), (1, 2)))
2903-
2904-
_testcapi.toggle_reftrace_counter()
2905-
g()
2906-
refs = _testcapi.toggle_reftrace_counter()
2907-
self.assertIn(refs, ((3, 3), (3, 4)))
2889+
code = textwrap.dedent("""
2890+
import _testcapi
2891+
_testcapi.toggle_reftrace_printer(True)
2892+
l1 = []
2893+
l2 = []
2894+
del l1
2895+
del l2
2896+
_testcapi.toggle_reftrace_printer(False)
2897+
""")
2898+
_, out, _ = assert_python_ok("-c", code)
2899+
lines = out.decode("utf-8").splitlines()
2900+
self.assertEqual(lines.count("CREATE list"), 2)
2901+
self.assertEqual(lines.count("DESTROY list"), 2)
29082902

29092903

29102904
if __name__ == "__main__":

Modules/_testcapimodule.c

Lines changed: 10 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -2515,108 +2515,31 @@ code_offset_to_line(PyObject* self, PyObject* const* args, Py_ssize_t nargsf)
25152515
}
25162516

25172517

2518-
typedef struct {
2519-
Py_ssize_t create_count;
2520-
Py_ssize_t destroy_count;
2521-
void *prev_data;
2522-
int (*prev_tracer)(PyObject *, PyRefTracerEvent, void *);
2523-
} reftrace_counter_data;
2524-
25252518
static int
2526-
_reftrace_counter(PyObject *obj, PyRefTracerEvent event, void *counter_data)
2519+
_reftrace_printer(PyObject *obj, PyRefTracerEvent event, void *counter_data)
25272520
{
25282521
if (event == PyRefTracer_CREATE) {
2529-
((reftrace_counter_data *)counter_data)->create_count++;
2522+
printf("CREATE %s\n", Py_TYPE(obj)->tp_name);
25302523
}
25312524
else { // PyRefTracer_DESTROY
2532-
((reftrace_counter_data *)counter_data)->destroy_count++;
2525+
printf("DESTROY %s\n", Py_TYPE(obj)->tp_name);
25332526
}
25342527
return 0;
25352528
}
25362529

2537-
void
2538-
reftrace_counter_capsule_destructor(PyObject *capsule)
2539-
{
2540-
reftrace_counter_data *counter_data = (reftrace_counter_data *)PyCapsule_GetPointer(capsule, "counter_data");
2541-
2542-
if (counter_data) {
2543-
if (counter_data->prev_tracer != (void *)_reftrace_counter) {
2544-
// juuust in case, to not segfault
2545-
PyRefTracer_SetTracer(counter_data->prev_tracer, counter_data->prev_data);
2546-
}
2547-
2548-
PyMem_Free(counter_data);
2549-
}
2550-
}
2551-
2552-
// A simple reftrace counter for very simple tests
2530+
// A simple reftrace printer for very simple tests
25532531
static PyObject *
2554-
toggle_reftrace_counter(PyObject *ob, PyObject *args)
2532+
toggle_reftrace_printer(PyObject *ob, PyObject *arg)
25552533
{
2556-
reftrace_counter_data *counter_data;
2557-
PyObject *capsule;
2558-
2559-
if (PyObject_GetOptionalAttrString(ob, "_reftrace_counter_data", &capsule)) {
2560-
if (!PyCapsule_IsValid(capsule, "counter_data")) {
2561-
PyErr_SetString(PyExc_ValueError, "something went wrong, _reftrace_counter_data is invalid");
2562-
return NULL;
2563-
}
2564-
2565-
counter_data = PyCapsule_GetPointer(capsule, "counter_data");
2566-
2567-
if (counter_data == NULL) {
2568-
PyErr_SetString(PyExc_ValueError, "something went wrong, _reftrace_counter_data is invalid");
2569-
return NULL;
2570-
}
2534+
if (arg == Py_True) {
2535+
PyRefTracer_SetTracer(_reftrace_printer, NULL);
25712536
}
25722537
else {
2573-
counter_data = (reftrace_counter_data *)PyMem_Malloc(sizeof(reftrace_counter_data));
2574-
2575-
if (counter_data == NULL) {
2576-
PyErr_NoMemory();
2577-
return NULL;
2578-
}
2579-
2580-
capsule = PyCapsule_New(counter_data, "counter_data", reftrace_counter_capsule_destructor);
2581-
2582-
if (capsule == NULL) {
2583-
PyMem_Free(counter_data);
2584-
return NULL;
2585-
}
2586-
2587-
counter_data->prev_tracer = (void *)_reftrace_counter; // sentinel
2588-
2589-
if (PyModule_Add(ob, "_reftrace_counter_data", capsule)) {
2590-
return NULL;
2591-
}
2592-
2593-
Py_INCREF(capsule);
2594-
}
2595-
2596-
if (counter_data->prev_tracer == (void *)_reftrace_counter) {
2597-
// toggle counter on
2598-
counter_data->create_count = counter_data->destroy_count = 0;
2599-
counter_data->prev_tracer = PyRefTracer_GetTracer(&counter_data->prev_data);
2600-
2601-
PyRefTracer_SetTracer(_reftrace_counter, counter_data);
2602-
2603-
Py_DECREF(capsule);
2604-
Py_RETURN_NONE;
2538+
PyRefTracer_SetTracer(NULL, NULL);
26052539
}
2606-
2607-
// toggle counter off
2608-
PyRefTracer_SetTracer(counter_data->prev_tracer, counter_data->prev_data);
2609-
2610-
Py_ssize_t create_count = counter_data->create_count - 1; // because of PyObject_GetOptionalAttrString
2611-
Py_ssize_t destroy_count = counter_data->destroy_count;
2612-
counter_data->prev_tracer = (void *)_reftrace_counter;
2613-
2614-
Py_DECREF(capsule);
2615-
2616-
return Py_BuildValue("(nn)", create_count, destroy_count);
2540+
Py_RETURN_NONE;
26172541
}
26182542

2619-
26202543
static PyMethodDef TestMethods[] = {
26212544
{"set_errno", set_errno, METH_VARARGS},
26222545
{"test_config", test_config, METH_NOARGS},
@@ -2710,7 +2633,7 @@ static PyMethodDef TestMethods[] = {
27102633
{"finalize_thread_hang", finalize_thread_hang, METH_O, NULL},
27112634
{"test_atexit", test_atexit, METH_NOARGS},
27122635
{"code_offset_to_line", _PyCFunction_CAST(code_offset_to_line), METH_FASTCALL},
2713-
{"toggle_reftrace_counter", toggle_reftrace_counter, METH_VARARGS},
2636+
{"toggle_reftrace_printer", toggle_reftrace_printer, METH_O},
27142637
{NULL, NULL} /* sentinel */
27152638
};
27162639

0 commit comments

Comments
 (0)