diff options
Diffstat (limited to 'Python/ceval.c')
-rw-r--r-- | Python/ceval.c | 56 |
1 files changed, 36 insertions, 20 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index e6b7424..fe8aca5 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -497,6 +497,7 @@ Py_MakePendingCalls(void) /* The interpreter's recursion limit */ static int recursion_limit = 1000; +int _Py_CheckRecursionLimit = 1000; int Py_GetRecursionLimit(void) @@ -508,8 +509,38 @@ void Py_SetRecursionLimit(int new_limit) { recursion_limit = new_limit; + _Py_CheckRecursionLimit = recursion_limit; } +/* the macro Py_EnterRecursiveCall() only calls _Py_CheckRecursiveCall() + if the recursion_depth reaches _Py_CheckRecursionLimit. + If USE_STACKCHECK, the macro decrements _Py_CheckRecursionLimit + to guarantee that _Py_CheckRecursiveCall() is regularly called. + Without USE_STACKCHECK, there is no need for this. */ +int +_Py_CheckRecursiveCall(char *where) +{ + PyThreadState *tstate = PyThreadState_GET(); + +#ifdef USE_STACKCHECK + if (PyOS_CheckStack()) { + --tstate->recursion_depth; + PyErr_SetString(PyExc_MemoryError, "Stack overflow"); + return -1; + } +#endif + if (tstate->recursion_depth > recursion_limit) { + --tstate->recursion_depth; + PyErr_Format(PyExc_RuntimeError, + "maximum recursion depth exceeded%s", + where); + return -1; + } + _Py_CheckRecursionLimit = recursion_limit; + return 0; +} + + /* Status code for main loop (reason for stack unwind) */ enum why_code { @@ -674,21 +705,9 @@ eval_frame(PyFrameObject *f) if (f == NULL) return NULL; -#ifdef USE_STACKCHECK - if (tstate->recursion_depth%10 == 0 && PyOS_CheckStack()) { - PyErr_SetString(PyExc_MemoryError, "Stack overflow"); - return NULL; - } -#endif - /* push frame */ - if (++tstate->recursion_depth > recursion_limit) { - --tstate->recursion_depth; - PyErr_SetString(PyExc_RuntimeError, - "maximum recursion depth exceeded"); - tstate->frame = f->f_back; + if (Py_EnterRecursiveCall("")) return NULL; - } tstate->frame = f; @@ -710,9 +729,7 @@ eval_frame(PyFrameObject *f) if (call_trace(tstate->c_tracefunc, tstate->c_traceobj, f, PyTrace_CALL, Py_None)) { /* Trace function raised an error */ - --tstate->recursion_depth; - tstate->frame = f->f_back; - return NULL; + goto exit_eval_frame; } } if (tstate->c_profilefunc != NULL) { @@ -722,9 +739,7 @@ eval_frame(PyFrameObject *f) tstate->c_profileobj, f, PyTrace_CALL, Py_None)) { /* Profile function raised an error */ - --tstate->recursion_depth; - tstate->frame = f->f_back; - return NULL; + goto exit_eval_frame; } } } @@ -2428,7 +2443,8 @@ eval_frame(PyFrameObject *f) reset_exc_info(tstate); /* pop frame */ - --tstate->recursion_depth; + exit_eval_frame: + Py_LeaveRecursiveCall(); tstate->frame = f->f_back; return retval; |