diff options
-rw-r--r-- | Modules/_testinternalcapi.c | 147 | ||||
-rw-r--r-- | Tools/c-analyzer/cpython/globals-to-fix.tsv | 1 | ||||
-rw-r--r-- | Tools/c-analyzer/cpython/ignored.tsv | 2 |
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 - |