mirror of
https://github.com/python/cpython.git
synced 2025-10-22 14:42:22 +00:00
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:
parent
c88b99ce06
commit
ee5adfbae6
4 changed files with 84 additions and 15 deletions
|
@ -148,6 +148,13 @@ generally one higher than you might expect, because it includes the
|
||||||
(temporary) reference as an argument to \function{getrefcount()}.
|
(temporary) reference as an argument to \function{getrefcount()}.
|
||||||
\end{funcdesc}
|
\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}
|
\begin{datadesc}{hexversion}
|
||||||
The version number encoded as a single integer. This is guaranteed to
|
The version number encoded as a single integer. This is guaranteed to
|
||||||
increase with each version, including proper support for
|
increase with each version, including proper support for
|
||||||
|
@ -275,6 +282,17 @@ maximizing responsiveness as well as overhead.
|
||||||
\index{profile function}
|
\index{profile function}
|
||||||
\index{profiler}
|
\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}
|
\begin{funcdesc}{settrace}{tracefunc}
|
||||||
Set the system's trace function, which allows you to implement a
|
Set the system's trace function, which allows you to implement a
|
||||||
Python source code debugger in Python. See section ``How It Works''
|
Python source code debugger in Python. See section ``How It Works''
|
||||||
|
|
|
@ -443,13 +443,6 @@ typedef unsigned long uintptr_t;
|
||||||
#define SIZEOF_LONG 4
|
#define SIZEOF_LONG 4
|
||||||
#define SIZEOF_LONG_LONG 8
|
#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
|
/* EXPERIMENTAL FEATURE: When CHECK_IMPORT_CASE is defined, check case of
|
||||||
imported modules against case of file; this causes "import String" to fail
|
imported modules against case of file; this causes "import String" to fail
|
||||||
with a NameError exception when it finds "string.py". Normally, you set
|
with a NameError exception when it finds "string.py". Normally, you set
|
||||||
|
|
|
@ -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) */
|
/* Status code for main loop (reason for stack unwind) */
|
||||||
|
|
||||||
enum why_code {
|
enum why_code {
|
||||||
|
@ -326,10 +340,6 @@ PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals)
|
||||||
|
|
||||||
/* Interpreter main loop */
|
/* Interpreter main loop */
|
||||||
|
|
||||||
#ifndef MAX_RECURSION_DEPTH
|
|
||||||
#define MAX_RECURSION_DEPTH 10000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
||||||
PyObject **args, int argcount, PyObject **kws, int kwcount,
|
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;
|
--tstate->recursion_depth;
|
||||||
PyErr_SetString(PyExc_RuntimeError,
|
PyErr_SetString(PyExc_RuntimeError,
|
||||||
"Maximum recursion depth exceeded");
|
"Maximum recursion depth exceeded");
|
||||||
|
|
|
@ -199,6 +199,45 @@ static char setcheckinterval_doc[] =
|
||||||
Tell the Python interpreter to check for asynchronous events every\n\
|
Tell the Python interpreter to check for asynchronous events every\n\
|
||||||
n instructions. This also affects how often thread switches occur.";
|
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
|
#ifdef USE_MALLOPT
|
||||||
/* Link with -lmalloc (or -lmpc) on an SGI */
|
/* Link with -lmalloc (or -lmpc) on an SGI */
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
@ -268,7 +307,8 @@ static PyMethodDef sys_methods[] = {
|
||||||
/* Might as well keep this in alphabetic order */
|
/* Might as well keep this in alphabetic order */
|
||||||
{"exc_info", sys_exc_info, 1, exc_info_doc},
|
{"exc_info", sys_exc_info, 1, exc_info_doc},
|
||||||
{"exit", sys_exit, 0, exit_doc},
|
{"exit", sys_exit, 0, exit_doc},
|
||||||
{"getdefaultencoding", sys_getdefaultencoding, 1, getdefaultencoding_doc},
|
{"getdefaultencoding", sys_getdefaultencoding, 1,
|
||||||
|
getdefaultencoding_doc},
|
||||||
#ifdef COUNT_ALLOCS
|
#ifdef COUNT_ALLOCS
|
||||||
{"getcounts", sys_getcounts, 1},
|
{"getcounts", sys_getcounts, 1},
|
||||||
#endif
|
#endif
|
||||||
|
@ -280,12 +320,18 @@ static PyMethodDef sys_methods[] = {
|
||||||
{"gettotalrefcount", sys_gettotalrefcount, 1},
|
{"gettotalrefcount", sys_gettotalrefcount, 1},
|
||||||
#endif
|
#endif
|
||||||
{"getrefcount", sys_getrefcount, 1, getrefcount_doc},
|
{"getrefcount", sys_getrefcount, 1, getrefcount_doc},
|
||||||
|
{"getrecursionlimit", sys_getrecursionlimit, 1,
|
||||||
|
getrecursionlimit_doc},
|
||||||
#ifdef USE_MALLOPT
|
#ifdef USE_MALLOPT
|
||||||
{"mdebug", sys_mdebug, 1},
|
{"mdebug", sys_mdebug, 1},
|
||||||
#endif
|
#endif
|
||||||
{"setdefaultencoding", sys_setdefaultencoding, 1, setdefaultencoding_doc},
|
{"setdefaultencoding", sys_setdefaultencoding, 1,
|
||||||
{"setcheckinterval", sys_setcheckinterval, 1, setcheckinterval_doc},
|
setdefaultencoding_doc},
|
||||||
|
{"setcheckinterval", sys_setcheckinterval, 1,
|
||||||
|
setcheckinterval_doc},
|
||||||
{"setprofile", sys_setprofile, 0, setprofile_doc},
|
{"setprofile", sys_setprofile, 0, setprofile_doc},
|
||||||
|
{"setrecursionlimit", sys_setrecursionlimit, 1,
|
||||||
|
setrecursionlimit_doc},
|
||||||
{"settrace", sys_settrace, 0, settrace_doc},
|
{"settrace", sys_settrace, 0, settrace_doc},
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
@ -376,8 +422,10 @@ Functions:\n\
|
||||||
exc_info() -- return thread-safe information about the current exception\n\
|
exc_info() -- return thread-safe information about the current exception\n\
|
||||||
exit() -- exit the interpreter by raising SystemExit\n\
|
exit() -- exit the interpreter by raising SystemExit\n\
|
||||||
getrefcount() -- return the reference count for an object (plus one :-)\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\
|
setcheckinterval() -- control how often the interpreter checks for events\n\
|
||||||
setprofile() -- set the global profiling function\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\
|
settrace() -- set the global debug tracing function\n\
|
||||||
"
|
"
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue