summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Galindo <Pablogsal@gmail.com>2021-02-28 22:41:09 (GMT)
committerGitHub <noreply@github.com>2021-02-28 22:41:09 (GMT)
commitaf5fa13ef6f648fc7a7a33a7556db13887e7d643 (patch)
treefaa0ffb9e99a6ae822b9c464a7cb044a8dc8e94f
parente8f5ddd33e44dae4e0121f87a7bf92d754807e49 (diff)
downloadcpython-af5fa13ef6f648fc7a7a33a7556db13887e7d643.zip
cpython-af5fa13ef6f648fc7a7a33a7556db13887e7d643.tar.gz
cpython-af5fa13ef6f648fc7a7a33a7556db13887e7d643.tar.bz2
bpo-37146: Deactivate opcode cache only when using huntrleaks in the test suite (GH-24643)
-rw-r--r--Include/cpython/ceval.h2
-rw-r--r--Lib/test/libregrtest/setup.py1
-rw-r--r--Python/ceval.c22
-rw-r--r--Python/clinic/sysmodule.c.h20
-rw-r--r--Python/sysmodule.c15
5 files changed, 49 insertions, 11 deletions
diff --git a/Include/cpython/ceval.h b/Include/cpython/ceval.h
index 0633892..05dcfac 100644
--- a/Include/cpython/ceval.h
+++ b/Include/cpython/ceval.h
@@ -28,3 +28,5 @@ PyAPI_FUNC(Py_ssize_t) _PyEval_RequestCodeExtraIndex(freefunc);
PyAPI_FUNC(int) _PyEval_SliceIndex(PyObject *, Py_ssize_t *);
PyAPI_FUNC(int) _PyEval_SliceIndexNotNone(PyObject *, Py_ssize_t *);
+
+PyAPI_FUNC(void) _PyEval_DeactivateOpCache(void);
diff --git a/Lib/test/libregrtest/setup.py b/Lib/test/libregrtest/setup.py
index 1f264c1..7738d4f 100644
--- a/Lib/test/libregrtest/setup.py
+++ b/Lib/test/libregrtest/setup.py
@@ -62,6 +62,7 @@ def setup_tests(ns):
if ns.huntrleaks:
unittest.BaseTestSuite._cleanup = False
+ sys._deactivate_opcache()
if ns.memlimit is not None:
support.set_memlimit(ns.memlimit)
diff --git a/Python/ceval.c b/Python/ceval.c
index 7862643..8ec00bc 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -107,17 +107,19 @@ static long dxp[256];
#endif
/* per opcode cache */
-#ifdef Py_DEBUG
-// --with-pydebug is used to find memory leak. opcache makes it harder.
-// So we disable opcache when Py_DEBUG is defined.
-// See bpo-37146
-#define OPCACHE_MIN_RUNS 0 /* disable opcache */
-#else
-#define OPCACHE_MIN_RUNS 1024 /* create opcache when code executed this time */
-#endif
+static int opcache_min_runs = 1024; /* create opcache when code executed this many times */
#define OPCODE_CACHE_MAX_TRIES 20
#define OPCACHE_STATS 0 /* Enable stats */
+// This function allows to deactivate the opcode cache. As different cache mechanisms may hold
+// references, this can mess with the reference leak detector functionality so the cache needs
+// to be deactivated in such scenarios to avoid false positives. See bpo-3714 for more information.
+void
+_PyEval_DeactivateOpCache(void)
+{
+ opcache_min_runs = 0;
+}
+
#if OPCACHE_STATS
static size_t opcache_code_objects = 0;
static size_t opcache_code_objects_extra_mem = 0;
@@ -1705,9 +1707,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
f->f_stackdepth = -1;
f->f_state = FRAME_EXECUTING;
- if (co->co_opcache_flag < OPCACHE_MIN_RUNS) {
+ if (co->co_opcache_flag < opcache_min_runs) {
co->co_opcache_flag++;
- if (co->co_opcache_flag == OPCACHE_MIN_RUNS) {
+ if (co->co_opcache_flag == opcache_min_runs) {
if (_PyCode_InitOpcache(co) < 0) {
goto exit_eval_frame;
}
diff --git a/Python/clinic/sysmodule.c.h b/Python/clinic/sysmodule.c.h
index addd589..04c8481 100644
--- a/Python/clinic/sysmodule.c.h
+++ b/Python/clinic/sysmodule.c.h
@@ -938,6 +938,24 @@ sys_getandroidapilevel(PyObject *module, PyObject *Py_UNUSED(ignored))
#endif /* defined(ANDROID_API_LEVEL) */
+PyDoc_STRVAR(sys__deactivate_opcache__doc__,
+"_deactivate_opcache($module, /)\n"
+"--\n"
+"\n"
+"Deactivate the opcode cache permanently");
+
+#define SYS__DEACTIVATE_OPCACHE_METHODDEF \
+ {"_deactivate_opcache", (PyCFunction)sys__deactivate_opcache, METH_NOARGS, sys__deactivate_opcache__doc__},
+
+static PyObject *
+sys__deactivate_opcache_impl(PyObject *module);
+
+static PyObject *
+sys__deactivate_opcache(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+ return sys__deactivate_opcache_impl(module);
+}
+
#ifndef SYS_GETWINDOWSVERSION_METHODDEF
#define SYS_GETWINDOWSVERSION_METHODDEF
#endif /* !defined(SYS_GETWINDOWSVERSION_METHODDEF) */
@@ -965,4 +983,4 @@ sys_getandroidapilevel(PyObject *module, PyObject *Py_UNUSED(ignored))
#ifndef SYS_GETANDROIDAPILEVEL_METHODDEF
#define SYS_GETANDROIDAPILEVEL_METHODDEF
#endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */
-/*[clinic end generated code: output=bbc4963fe86a29d9 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=68c62b9ca317a0c8 input=a9049054013a1b77]*/
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index 13b9034..686b6ca 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -1958,6 +1958,20 @@ sys_getandroidapilevel_impl(PyObject *module)
#endif /* ANDROID_API_LEVEL */
+/*[clinic input]
+sys._deactivate_opcache
+
+Deactivate the opcode cache permanently
+[clinic start generated code]*/
+
+static PyObject *
+sys__deactivate_opcache_impl(PyObject *module)
+/*[clinic end generated code: output=00e20982bd012122 input=501eac146735ccf9]*/
+{
+ _PyEval_DeactivateOpCache();
+ Py_RETURN_NONE;
+}
+
static PyMethodDef sys_methods[] = {
/* Might as well keep this in alphabetic order */
@@ -2011,6 +2025,7 @@ static PyMethodDef sys_methods[] = {
SYS_GET_ASYNCGEN_HOOKS_METHODDEF
SYS_GETANDROIDAPILEVEL_METHODDEF
SYS_UNRAISABLEHOOK_METHODDEF
+ SYS__DEACTIVATE_OPCACHE_METHODDEF
{NULL, NULL} /* sentinel */
};