[Python-checkins] bpo-31857: Make the behavior of USE_STACKCHECK deterministic (#4098)
Benjamin Peterson
webhook-mailer at python.org
Thu Oct 26 02:03:08 EDT 2017
https://github.com/python/cpython/commit/1896793520a49a6f97ae360c0b288967e56b005e
commit: 1896793520a49a6f97ae360c0b288967e56b005e
branch: master
author: pdox <pdox at alum.mit.edu>
committer: Benjamin Peterson <benjamin at python.org>
date: 2017-10-25T23:03:01-07:00
summary:
bpo-31857: Make the behavior of USE_STACKCHECK deterministic (#4098)
files:
A Misc/NEWS.d/next/Windows/2017-10-23-18-35-50.bpo-31857.YwhEvc.rst
M Include/ceval.h
M Include/internal/ceval.h
M Include/pystate.h
M Python/ceval.c
M Python/pystate.c
diff --git a/Include/ceval.h b/Include/ceval.h
index c5ccf473c17..70306b8bbd8 100644
--- a/Include/ceval.h
+++ b/Include/ceval.h
@@ -93,21 +93,19 @@ PyAPI_FUNC(int) Py_GetRecursionLimit(void);
PyThreadState_GET()->overflowed = 0; \
} while(0)
PyAPI_FUNC(int) _Py_CheckRecursiveCall(const char *where);
-/* XXX _Py_CheckRecursionLimit should be changed to
- _PyRuntime.ceval.check_recursion_limit. However, due to the macros
- in which it's used, _Py_CheckRecursionLimit is stuck in the stable
- ABI. It should be removed therefrom when possible.
+
+/* Due to the macros in which it's used, _Py_CheckRecursionLimit is in
+ the stable ABI. It should be removed therefrom when possible.
*/
PyAPI_DATA(int) _Py_CheckRecursionLimit;
#ifdef USE_STACKCHECK
-/* With USE_STACKCHECK, we artificially decrement the recursion limit in order
- to trigger regular stack checks in _Py_CheckRecursiveCall(), except if
- the "overflowed" flag is set, in which case we need the true value
- of _Py_CheckRecursionLimit for _Py_MakeEndRecCheck() to function properly.
+/* With USE_STACKCHECK, trigger stack checks in _Py_CheckRecursiveCall()
+ on every 64th call to Py_EnterRecursiveCall.
*/
# define _Py_MakeRecCheck(x) \
- (++(x) > (_Py_CheckRecursionLimit += PyThreadState_GET()->overflowed - 1))
+ (++(x) > _Py_CheckRecursionLimit || \
+ ++(PyThreadState_GET()->stackcheck_counter) > 64)
#else
# define _Py_MakeRecCheck(x) (++(x) > _Py_CheckRecursionLimit)
#endif
diff --git a/Include/internal/ceval.h b/Include/internal/ceval.h
index 57db9b1ebc7..cdabb9521d1 100644
--- a/Include/internal/ceval.h
+++ b/Include/internal/ceval.h
@@ -29,7 +29,6 @@ struct _pending_calls {
struct _ceval_runtime_state {
int recursion_limit;
- int check_recursion_limit;
/* Records whether tracing is on for any thread. Counts the number
of threads for which tstate->c_tracefunc is non-NULL, so if the
value is 0, we know we don't have to check this thread's
diff --git a/Include/pystate.h b/Include/pystate.h
index 238008fce47..0821238a0ac 100644
--- a/Include/pystate.h
+++ b/Include/pystate.h
@@ -151,6 +151,8 @@ typedef struct _ts {
to handle the runtime error. */
char recursion_critical; /* The current calls must not cause
a stack overflow. */
+ int stackcheck_counter;
+
/* 'tracing' keeps track of the execution depth when tracing/profiling.
This is to prevent the actual trace/profile code from being recorded in
the trace/profile. */
diff --git a/Misc/NEWS.d/next/Windows/2017-10-23-18-35-50.bpo-31857.YwhEvc.rst b/Misc/NEWS.d/next/Windows/2017-10-23-18-35-50.bpo-31857.YwhEvc.rst
new file mode 100644
index 00000000000..13a49780776
--- /dev/null
+++ b/Misc/NEWS.d/next/Windows/2017-10-23-18-35-50.bpo-31857.YwhEvc.rst
@@ -0,0 +1,2 @@
+Make the behavior of USE_STACKCHECK deterministic in a multi-threaded
+environment.
diff --git a/Python/ceval.c b/Python/ceval.c
index 58a2513b3ef..f6519cff590 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -469,13 +469,15 @@ _Py_CheckRecursiveCall(const char *where)
int recursion_limit = _PyRuntime.ceval.recursion_limit;
#ifdef USE_STACKCHECK
+ tstate->stackcheck_counter = 0;
if (PyOS_CheckStack()) {
--tstate->recursion_depth;
PyErr_SetString(PyExc_MemoryError, "Stack overflow");
return -1;
}
-#endif
+ /* Needed for ABI backwards-compatibility (see bpo-31857) */
_Py_CheckRecursionLimit = recursion_limit;
+#endif
if (tstate->recursion_critical)
/* Somebody asked that we don't check for recursion. */
return 0;
diff --git a/Python/pystate.c b/Python/pystate.c
index d85d604de5e..82ebf4da7db 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -245,6 +245,7 @@ new_threadstate(PyInterpreterState *interp, int init)
tstate->recursion_depth = 0;
tstate->overflowed = 0;
tstate->recursion_critical = 0;
+ tstate->stackcheck_counter = 0;
tstate->tracing = 0;
tstate->use_tracing = 0;
tstate->gilstate_counter = 0;
More information about the Python-checkins
mailing list