summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Modules/_testinternalcapi.c147
-rw-r--r--Tools/c-analyzer/cpython/globals-to-fix.tsv1
-rw-r--r--Tools/c-analyzer/cpython/ignored.tsv2
3 files changed, 117 insertions, 33 deletions
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c
index b14b8ac..f53929f 100644
--- a/Modules/_testinternalcapi.c
+++ b/Modules/_testinternalcapi.c
@@ -28,6 +28,60 @@
#include "clinic/_testinternalcapi.c.h"
+
+#define MODULE_NAME "_testinternalcapi"
+
+
+static PyObject *
+_get_current_module(void)
+{
+ // We ensured it was imported in _run_script().
+ PyObject *name = PyUnicode_FromString(MODULE_NAME);
+ if (name == NULL) {
+ return NULL;
+ }
+ PyObject *mod = PyImport_GetModule(name);
+ Py_DECREF(name);
+ if (mod == NULL) {
+ return NULL;
+ }
+ assert(mod != Py_None);
+ return mod;
+}
+
+
+/* module state *************************************************************/
+
+typedef struct {
+ PyObject *record_list;
+} module_state;
+
+static inline module_state *
+get_module_state(PyObject *mod)
+{
+ assert(mod != NULL);
+ module_state *state = PyModule_GetState(mod);
+ assert(state != NULL);
+ return state;
+}
+
+static int
+traverse_module_state(module_state *state, visitproc visit, void *arg)
+{
+ Py_VISIT(state->record_list);
+ return 0;
+}
+
+static int
+clear_module_state(module_state *state)
+{
+ Py_CLEAR(state->record_list);
+ return 0;
+}
+
+
+/* module functions *********************************************************/
+
/*[clinic input]
module _testinternalcapi
[clinic start generated code]*/
@@ -496,13 +550,12 @@ decode_locale_ex(PyObject *self, PyObject *args)
return res;
}
-static PyObject *record_list = NULL;
-
static PyObject *
set_eval_frame_default(PyObject *self, PyObject *Py_UNUSED(args))
{
+ module_state *state = get_module_state(self);
_PyInterpreterState_SetEvalFrameFunc(PyInterpreterState_Get(), _PyEval_EvalFrameDefault);
- Py_CLEAR(record_list);
+ Py_CLEAR(state->record_list);
Py_RETURN_NONE;
}
@@ -510,7 +563,10 @@ static PyObject *
record_eval(PyThreadState *tstate, struct _PyInterpreterFrame *f, int exc)
{
if (PyFunction_Check(f->f_funcobj)) {
- PyList_Append(record_list, ((PyFunctionObject *)f->f_funcobj)->func_name);
+ PyObject *module = _get_current_module();
+ assert(module != NULL);
+ module_state *state = get_module_state(module);
+ PyList_Append(state->record_list, ((PyFunctionObject *)f->f_funcobj)->func_name);
}
return _PyEval_EvalFrameDefault(tstate, f, exc);
}
@@ -519,11 +575,12 @@ record_eval(PyThreadState *tstate, struct _PyInterpreterFrame *f, int exc)
static PyObject *
set_eval_frame_record(PyObject *self, PyObject *list)
{
+ module_state *state = get_module_state(self);
if (!PyList_Check(list)) {
PyErr_SetString(PyExc_TypeError, "argument must be a list");
return NULL;
}
- Py_XSETREF(record_list, Py_NewRef(list));
+ Py_XSETREF(state->record_list, Py_NewRef(list));
_PyInterpreterState_SetEvalFrameFunc(PyInterpreterState_Get(), record_eval);
Py_RETURN_NONE;
}
@@ -613,7 +670,7 @@ get_interp_settings(PyObject *self, PyObject *args)
}
-static PyMethodDef TestMethods[] = {
+static PyMethodDef module_functions[] = {
{"get_configs", get_configs, METH_NOARGS},
{"get_recursion_depth", get_recursion_depth, METH_NOARGS},
{"test_bswap", test_bswap, METH_NOARGS},
@@ -638,35 +695,65 @@ static PyMethodDef TestMethods[] = {
};
-static struct PyModuleDef _testcapimodule = {
- PyModuleDef_HEAD_INIT,
- "_testinternalcapi",
- NULL,
- -1,
- TestMethods,
- NULL,
- NULL,
- NULL,
- NULL
-};
-
+/* initialization function */
-PyMODINIT_FUNC
-PyInit__testinternalcapi(void)
+static int
+module_exec(PyObject *module)
{
- PyObject *module = PyModule_Create(&_testcapimodule);
- if (module == NULL) {
- return NULL;
- }
-
if (PyModule_AddObject(module, "SIZEOF_PYGC_HEAD",
PyLong_FromSsize_t(sizeof(PyGC_Head))) < 0) {
- goto error;
+ return 1;
}
- return module;
+ return 0;
+}
-error:
- Py_DECREF(module);
- return NULL;
+static struct PyModuleDef_Slot module_slots[] = {
+ {Py_mod_exec, module_exec},
+ {0, NULL},
+};
+
+static int
+module_traverse(PyObject *module, visitproc visit, void *arg)
+{
+ module_state *state = get_module_state(module);
+ assert(state != NULL);
+ traverse_module_state(state, visit, arg);
+ return 0;
+}
+
+static int
+module_clear(PyObject *module)
+{
+ module_state *state = get_module_state(module);
+ assert(state != NULL);
+ (void)clear_module_state(state);
+ return 0;
+}
+
+static void
+module_free(void *module)
+{
+ module_state *state = get_module_state(module);
+ assert(state != NULL);
+ (void)clear_module_state(state);
+}
+
+static struct PyModuleDef _testcapimodule = {
+ .m_base = PyModuleDef_HEAD_INIT,
+ .m_name = MODULE_NAME,
+ .m_doc = NULL,
+ .m_size = sizeof(module_state),
+ .m_methods = module_functions,
+ .m_slots = module_slots,
+ .m_traverse = module_traverse,
+ .m_clear = module_clear,
+ .m_free = (freefunc)module_free,
+};
+
+
+PyMODINIT_FUNC
+PyInit__testinternalcapi(void)
+{
+ return PyModuleDef_Init(&_testcapimodule);
}
diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv
index 479221c..cd08782 100644
--- a/Tools/c-analyzer/cpython/globals-to-fix.tsv
+++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv
@@ -523,7 +523,6 @@ Modules/_asynciomodule.c - all_tasks -
Modules/_asynciomodule.c - current_tasks -
Modules/_asynciomodule.c - iscoroutine_typecache -
Modules/_ctypes/_ctypes.c - _ctypes_ptrtype_cache -
-Modules/_testinternalcapi.c - record_list -
Modules/_tkinter.c - tcl_lock -
Modules/_tkinter.c - excInCmd -
Modules/_tkinter.c - valInCmd -
diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv
index 0253169..849e20a 100644
--- a/Tools/c-analyzer/cpython/ignored.tsv
+++ b/Tools/c-analyzer/cpython/ignored.tsv
@@ -483,8 +483,6 @@ Modules/_testcapimodule.c - g_type_watchers_installed -
Modules/_testimportmultiple.c - _barmodule -
Modules/_testimportmultiple.c - _foomodule -
Modules/_testimportmultiple.c - _testimportmultiple -
-Modules/_testinternalcapi.c - TestMethods -
-Modules/_testinternalcapi.c - _testcapimodule -
Modules/_testmultiphase.c - Example_Type_slots -
Modules/_testmultiphase.c - Example_Type_spec -
Modules/_testmultiphase.c - Example_methods -