Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ee5adfb

Browse files
committed
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
1 parent c88b99c commit ee5adfb

4 files changed

Lines changed: 84 additions & 15 deletions

File tree

Doc/lib/libsys.tex

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,13 @@ \section{\module{sys} ---
148148
(temporary) reference as an argument to \function{getrefcount()}.
149149
\end{funcdesc}
150150

151+
\begin{funcdesc}{getrecursionlimit}{}
152+
Return the current value of the recursion limit, the maximum depth of
153+
the Python interpreter stack. This limit prevents infinite recursion
154+
from causing an overflow of the C stack and crashing Python. It can
155+
be set by \function{setrecursionlimit}.
156+
\end{funcdesc}
157+
151158
\begin{datadesc}{hexversion}
152159
The version number encoded as a single integer. This is guaranteed to
153160
increase with each version, including proper support for
@@ -275,6 +282,17 @@ \section{\module{sys} ---
275282
\index{profile function}
276283
\index{profiler}
277284

285+
\begin{funcdesc}{setrecursionlimit}{limit}
286+
Set the maximum depth of the Python interpreter stack to \var{limit}.
287+
This limit prevents infinite recursion from causing an overflow of the
288+
C stack and crashing Python.
289+
290+
The highest possible limit is platform-dependent. A user may need to
291+
set the limit higher when she has a program that requires deep
292+
recursion and a platform that supports a higher limit. This should be
293+
done with care, because a too-high limit can lead to a crash.
294+
\edn{funcdesc}
295+
278296
\begin{funcdesc}{settrace}{tracefunc}
279297
Set the system's trace function, which allows you to implement a
280298
Python source code debugger in Python. See section ``How It Works''

PC/config.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -443,13 +443,6 @@ typedef unsigned long uintptr_t;
443443
#define SIZEOF_LONG 4
444444
#define SIZEOF_LONG_LONG 8
445445

446-
/* Smaller stack size limit. (9500 would work too, but we're conservative.) */
447-
448-
#ifndef MAX_RECURSION_DEPTH
449-
#define MAX_RECURSION_DEPTH 5000
450-
#endif
451-
452-
453446
/* EXPERIMENTAL FEATURE: When CHECK_IMPORT_CASE is defined, check case of
454447
imported modules against case of file; this causes "import String" to fail
455448
with a NameError exception when it finds "string.py". Normally, you set

Python/ceval.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,20 @@ Py_MakePendingCalls(void)
298298
}
299299

300300

301+
/* The interpreter's recursion limit */
302+
303+
static int recursion_limit = 2500;
304+
305+
int Py_GetRecursionLimit(void)
306+
{
307+
return recursion_limit;
308+
}
309+
310+
void Py_SetRecursionLimit(int new_limit)
311+
{
312+
recursion_limit = new_limit;
313+
}
314+
301315
/* Status code for main loop (reason for stack unwind) */
302316

303317
enum why_code {
@@ -326,10 +340,6 @@ PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals)
326340

327341
/* Interpreter main loop */
328342

329-
#ifndef MAX_RECURSION_DEPTH
330-
#define MAX_RECURSION_DEPTH 10000
331-
#endif
332-
333343
static PyObject *
334344
eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
335345
PyObject **args, int argcount, PyObject **kws, int kwcount,
@@ -565,7 +575,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
565575
}
566576
}
567577

568-
if (++tstate->recursion_depth > MAX_RECURSION_DEPTH) {
578+
if (++tstate->recursion_depth > recursion_limit) {
569579
--tstate->recursion_depth;
570580
PyErr_SetString(PyExc_RuntimeError,
571581
"Maximum recursion depth exceeded");

Python/sysmodule.c

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,45 @@ static char setcheckinterval_doc[] =
199199
Tell the Python interpreter to check for asynchronous events every\n\
200200
n instructions. This also affects how often thread switches occur.";
201201

202+
static PyObject *
203+
sys_setrecursionlimit(PyObject *self, PyObject *args)
204+
{
205+
int new_limit;
206+
if (!PyArg_ParseTuple(args, "i:setrecursionlimit", &new_limit))
207+
return NULL;
208+
if (new_limit <= 0) {
209+
PyErr_SetString(PyExc_ValueError,
210+
"recursion limit must be positive");
211+
return NULL;
212+
}
213+
Py_SetRecursionLimit(new_limit);
214+
Py_INCREF(Py_None);
215+
return Py_None;
216+
}
217+
218+
static char setrecursionlimit_doc[] =
219+
"setrecursionlimit(n)\n\
220+
\n\
221+
Set the maximum depth of the Python interpreter stack to n. This\n\
222+
limit prevents infinite recursion from causing an overflow of the C\n\
223+
stack and crashing Python. The highest possible limit is platform-\n\
224+
dependent.";
225+
226+
static PyObject *
227+
sys_getrecursionlimit(PyObject *self, PyObject *args)
228+
{
229+
if (!PyArg_ParseTuple(args, ":getrecursionlimit"))
230+
return NULL;
231+
return PyInt_FromLong(Py_GetRecursionLimit());
232+
}
233+
234+
static char getrecursionlimit_doc[] =
235+
"getrecursionlimit()\n\
236+
\n\
237+
Return the current value of the recursion limit, the maximum depth\n\
238+
of the Python interpreter stack. This limit prevents infinite\n\
239+
recursion from causing an overflow of the C stack and crashing Python.";
240+
202241
#ifdef USE_MALLOPT
203242
/* Link with -lmalloc (or -lmpc) on an SGI */
204243
#include <malloc.h>
@@ -268,7 +307,8 @@ static PyMethodDef sys_methods[] = {
268307
/* Might as well keep this in alphabetic order */
269308
{"exc_info", sys_exc_info, 1, exc_info_doc},
270309
{"exit", sys_exit, 0, exit_doc},
271-
{"getdefaultencoding", sys_getdefaultencoding, 1, getdefaultencoding_doc},
310+
{"getdefaultencoding", sys_getdefaultencoding, 1,
311+
getdefaultencoding_doc},
272312
#ifdef COUNT_ALLOCS
273313
{"getcounts", sys_getcounts, 1},
274314
#endif
@@ -280,12 +320,18 @@ static PyMethodDef sys_methods[] = {
280320
{"gettotalrefcount", sys_gettotalrefcount, 1},
281321
#endif
282322
{"getrefcount", sys_getrefcount, 1, getrefcount_doc},
323+
{"getrecursionlimit", sys_getrecursionlimit, 1,
324+
getrecursionlimit_doc},
283325
#ifdef USE_MALLOPT
284326
{"mdebug", sys_mdebug, 1},
285327
#endif
286-
{"setdefaultencoding", sys_setdefaultencoding, 1, setdefaultencoding_doc},
287-
{"setcheckinterval", sys_setcheckinterval, 1, setcheckinterval_doc},
328+
{"setdefaultencoding", sys_setdefaultencoding, 1,
329+
setdefaultencoding_doc},
330+
{"setcheckinterval", sys_setcheckinterval, 1,
331+
setcheckinterval_doc},
288332
{"setprofile", sys_setprofile, 0, setprofile_doc},
333+
{"setrecursionlimit", sys_setrecursionlimit, 1,
334+
setrecursionlimit_doc},
289335
{"settrace", sys_settrace, 0, settrace_doc},
290336
{NULL, NULL} /* sentinel */
291337
};
@@ -376,8 +422,10 @@ Functions:\n\
376422
exc_info() -- return thread-safe information about the current exception\n\
377423
exit() -- exit the interpreter by raising SystemExit\n\
378424
getrefcount() -- return the reference count for an object (plus one :-)\n\
425+
getrecursionlimit() -- return the max recursion depth for the interpreter\n\
379426
setcheckinterval() -- control how often the interpreter checks for events\n\
380427
setprofile() -- set the global profiling function\n\
428+
setrecursionlimit() -- set the max recursion depth for the interpreter\n\
381429
settrace() -- set the global debug tracing function\n\
382430
"
383431
#endif

0 commit comments

Comments
 (0)