add user-modifiable recursion_limit

ceval.c:
    define recurion_limit (static), default value is 2500
    define Py_GetRecursionLimit and Py_SetRecursionLimit
    raise RuntimeError if limit is exceeded
PC/config.h:
    remove plat-specific definition
sysmodule.c:
    add sys.(get|set)recursionlimit
This commit is contained in:
Jeremy Hylton 2000-08-31 19:23:01 +00:00
parent c88b99ce06
commit ee5adfbae6
4 changed files with 84 additions and 15 deletions

View File

@ -148,6 +148,13 @@ generally one higher than you might expect, because it includes the
(temporary) reference as an argument to \function{getrefcount()}.
\end{funcdesc}
\begin{funcdesc}{getrecursionlimit}{}
Return the current value of the recursion limit, the maximum depth of
the Python interpreter stack. This limit prevents infinite recursion
from causing an overflow of the C stack and crashing Python. It can
be set by \function{setrecursionlimit}.
\end{funcdesc}
\begin{datadesc}{hexversion}
The version number encoded as a single integer. This is guaranteed to
increase with each version, including proper support for
@ -275,6 +282,17 @@ maximizing responsiveness as well as overhead.
\index{profile function}
\index{profiler}
\begin{funcdesc}{setrecursionlimit}{limit}
Set the maximum depth of the Python interpreter stack to \var{limit}.
This limit prevents infinite recursion from causing an overflow of the
C stack and crashing Python.
The highest possible limit is platform-dependent. A user may need to
set the limit higher when she has a program that requires deep
recursion and a platform that supports a higher limit. This should be
done with care, because a too-high limit can lead to a crash.
\edn{funcdesc}
\begin{funcdesc}{settrace}{tracefunc}
Set the system's trace function, which allows you to implement a
Python source code debugger in Python. See section ``How It Works''

View File

@ -443,13 +443,6 @@ typedef unsigned long uintptr_t;
#define SIZEOF_LONG 4
#define SIZEOF_LONG_LONG 8
/* Smaller stack size limit. (9500 would work too, but we're conservative.) */
#ifndef MAX_RECURSION_DEPTH
#define MAX_RECURSION_DEPTH 5000
#endif
/* EXPERIMENTAL FEATURE: When CHECK_IMPORT_CASE is defined, check case of
imported modules against case of file; this causes "import String" to fail
with a NameError exception when it finds "string.py". Normally, you set

View File

@ -298,6 +298,20 @@ Py_MakePendingCalls(void)
}
/* The interpreter's recursion limit */
static int recursion_limit = 2500;
int Py_GetRecursionLimit(void)
{
return recursion_limit;
}
void Py_SetRecursionLimit(int new_limit)
{
recursion_limit = new_limit;
}
/* Status code for main loop (reason for stack unwind) */
enum why_code {
@ -326,10 +340,6 @@ PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals)
/* Interpreter main loop */
#ifndef MAX_RECURSION_DEPTH
#define MAX_RECURSION_DEPTH 10000
#endif
static PyObject *
eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
PyObject **args, int argcount, PyObject **kws, int kwcount,
@ -565,7 +575,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
}
}
if (++tstate->recursion_depth > MAX_RECURSION_DEPTH) {
if (++tstate->recursion_depth > recursion_limit) {
--tstate->recursion_depth;
PyErr_SetString(PyExc_RuntimeError,
"Maximum recursion depth exceeded");

View File

@ -199,6 +199,45 @@ static char setcheckinterval_doc[] =
Tell the Python interpreter to check for asynchronous events every\n\
n instructions. This also affects how often thread switches occur.";
static PyObject *
sys_setrecursionlimit(PyObject *self, PyObject *args)
{
int new_limit;
if (!PyArg_ParseTuple(args, "i:setrecursionlimit", &new_limit))
return NULL;
if (new_limit <= 0) {
PyErr_SetString(PyExc_ValueError,
"recursion limit must be positive");
return NULL;
}
Py_SetRecursionLimit(new_limit);
Py_INCREF(Py_None);
return Py_None;
}
static char setrecursionlimit_doc[] =
"setrecursionlimit(n)\n\
\n\
Set the maximum depth of the Python interpreter stack to n. This\n\
limit prevents infinite recursion from causing an overflow of the C\n\
stack and crashing Python. The highest possible limit is platform-\n\
dependent.";
static PyObject *
sys_getrecursionlimit(PyObject *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, ":getrecursionlimit"))
return NULL;
return PyInt_FromLong(Py_GetRecursionLimit());
}
static char getrecursionlimit_doc[] =
"getrecursionlimit()\n\
\n\
Return the current value of the recursion limit, the maximum depth\n\
of the Python interpreter stack. This limit prevents infinite\n\
recursion from causing an overflow of the C stack and crashing Python.";
#ifdef USE_MALLOPT
/* Link with -lmalloc (or -lmpc) on an SGI */
#include <malloc.h>
@ -268,7 +307,8 @@ static PyMethodDef sys_methods[] = {
/* Might as well keep this in alphabetic order */
{"exc_info", sys_exc_info, 1, exc_info_doc},
{"exit", sys_exit, 0, exit_doc},
{"getdefaultencoding", sys_getdefaultencoding, 1, getdefaultencoding_doc},
{"getdefaultencoding", sys_getdefaultencoding, 1,
getdefaultencoding_doc},
#ifdef COUNT_ALLOCS
{"getcounts", sys_getcounts, 1},
#endif
@ -280,12 +320,18 @@ static PyMethodDef sys_methods[] = {
{"gettotalrefcount", sys_gettotalrefcount, 1},
#endif
{"getrefcount", sys_getrefcount, 1, getrefcount_doc},
{"getrecursionlimit", sys_getrecursionlimit, 1,
getrecursionlimit_doc},
#ifdef USE_MALLOPT
{"mdebug", sys_mdebug, 1},
#endif
{"setdefaultencoding", sys_setdefaultencoding, 1, setdefaultencoding_doc},
{"setcheckinterval", sys_setcheckinterval, 1, setcheckinterval_doc},
{"setdefaultencoding", sys_setdefaultencoding, 1,
setdefaultencoding_doc},
{"setcheckinterval", sys_setcheckinterval, 1,
setcheckinterval_doc},
{"setprofile", sys_setprofile, 0, setprofile_doc},
{"setrecursionlimit", sys_setrecursionlimit, 1,
setrecursionlimit_doc},
{"settrace", sys_settrace, 0, settrace_doc},
{NULL, NULL} /* sentinel */
};
@ -376,8 +422,10 @@ Functions:\n\
exc_info() -- return thread-safe information about the current exception\n\
exit() -- exit the interpreter by raising SystemExit\n\
getrefcount() -- return the reference count for an object (plus one :-)\n\
getrecursionlimit() -- return the max recursion depth for the interpreter\n\
setcheckinterval() -- control how often the interpreter checks for events\n\
setprofile() -- set the global profiling function\n\
setrecursionlimit() -- set the max recursion depth for the interpreter\n\
settrace() -- set the global debug tracing function\n\
"
#endif