diff options
author | scoder <stefan_ml@behnel.de> | 2021-04-28 16:12:16 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-28 16:12:16 (GMT) |
commit | 3cc481b9de43c234889c8010e7da3af7c0f42319 (patch) | |
tree | 1166babff0120ad235c37789907d640eec280c8f /Modules | |
parent | baecfbd849dbf42360d3a84af6cc13160838f24d (diff) | |
download | cpython-3cc481b9de43c234889c8010e7da3af7c0f42319.zip cpython-3cc481b9de43c234889c8010e7da3af7c0f42319.tar.gz cpython-3cc481b9de43c234889c8010e7da3af7c0f42319.tar.bz2 |
bpo-28254: Add a C-API for controlling the GC state (GH-25687)
Add new C-API functions to control the state of the garbage collector:
PyGC_Enable(), PyGC_Disable(), PyGC_IsEnabled(),
corresponding to the functions in the gc module.
Co-authored-by: Pablo Galindo <Pablogsal@gmail.com>
Co-authored-by: Victor Stinner <vstinner@python.org>
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_testcapimodule.c | 62 | ||||
-rw-r--r-- | Modules/gcmodule.c | 35 |
2 files changed, 91 insertions, 6 deletions
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index db62aea..26ebacb 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -144,6 +144,67 @@ test_sizeof_c_types(PyObject *self, PyObject *Py_UNUSED(ignored)) #endif } +static PyObject* +test_gc_control(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + int orig_enabled = PyGC_IsEnabled(); + const char* msg = "ok"; + int old_state; + + old_state = PyGC_Enable(); + msg = "Enable(1)"; + if (old_state != orig_enabled) { + goto failed; + } + msg = "IsEnabled(1)"; + if (!PyGC_IsEnabled()) { + goto failed; + } + + old_state = PyGC_Disable(); + msg = "disable(2)"; + if (!old_state) { + goto failed; + } + msg = "IsEnabled(2)"; + if (PyGC_IsEnabled()) { + goto failed; + } + + old_state = PyGC_Enable(); + msg = "enable(3)"; + if (old_state) { + goto failed; + } + msg = "IsEnabled(3)"; + if (!PyGC_IsEnabled()) { + goto failed; + } + + if (!orig_enabled) { + old_state = PyGC_Disable(); + msg = "disable(4)"; + if (old_state) { + goto failed; + } + msg = "IsEnabled(4)"; + if (PyGC_IsEnabled()) { + goto failed; + } + } + + Py_RETURN_NONE; + +failed: + /* Try to clean up if we can. */ + if (orig_enabled) { + PyGC_Enable(); + } else { + PyGC_Disable(); + } + PyErr_Format(TestError, "GC control failed in %s", msg); + return NULL; +} static PyObject* test_list_api(PyObject *self, PyObject *Py_UNUSED(ignored)) @@ -5544,6 +5605,7 @@ static PyMethodDef TestMethods[] = { {"PyDateTime_DATE_GET", test_PyDateTime_DATE_GET, METH_O}, {"PyDateTime_TIME_GET", test_PyDateTime_TIME_GET, METH_O}, {"PyDateTime_DELTA_GET", test_PyDateTime_DELTA_GET, METH_O}, + {"test_gc_control", test_gc_control, METH_NOARGS}, {"test_list_api", test_list_api, METH_NOARGS}, {"test_dict_iteration", test_dict_iteration, METH_NOARGS}, {"dict_getitem_knownhash", dict_getitem_knownhash, METH_VARARGS}, diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index d6b5142..e5e5aa3 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -1484,8 +1484,7 @@ static PyObject * gc_enable_impl(PyObject *module) /*[clinic end generated code: output=45a427e9dce9155c input=81ac4940ca579707]*/ { - GCState *gcstate = get_gc_state(); - gcstate->enabled = 1; + PyGC_Enable(); Py_RETURN_NONE; } @@ -1499,8 +1498,7 @@ static PyObject * gc_disable_impl(PyObject *module) /*[clinic end generated code: output=97d1030f7aa9d279 input=8c2e5a14e800d83b]*/ { - GCState *gcstate = get_gc_state(); - gcstate->enabled = 0; + PyGC_Disable(); Py_RETURN_NONE; } @@ -1514,8 +1512,7 @@ static int gc_isenabled_impl(PyObject *module) /*[clinic end generated code: output=1874298331c49130 input=30005e0422373b31]*/ { - GCState *gcstate = get_gc_state(); - return gcstate->enabled; + return PyGC_IsEnabled(); } /*[clinic input] @@ -2053,6 +2050,32 @@ PyInit_gc(void) return PyModuleDef_Init(&gcmodule); } +/* C API for controlling the state of the garbage collector */ +int +PyGC_Enable(void) +{ + GCState *gcstate = get_gc_state(); + int old_state = gcstate->enabled; + gcstate->enabled = 1; + return old_state; +} + +int +PyGC_Disable(void) +{ + GCState *gcstate = get_gc_state(); + int old_state = gcstate->enabled; + gcstate->enabled = 0; + return old_state; +} + +int +PyGC_IsEnabled(void) +{ + GCState *gcstate = get_gc_state(); + return gcstate->enabled; +} + /* Public API to invoke gc.collect() from C */ Py_ssize_t PyGC_Collect(void) |