diff options
author | xdegaye <xdegaye@gmail.com> | 2017-11-12 16:33:16 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-12 16:33:16 (GMT) |
commit | ea5b545e38b3fec7ff29276b5cd59dec583ebf34 (patch) | |
tree | 4916695b3b105810c0910fc129274e5dce35bc95 /Python | |
parent | 4e09deb127013f7cd097f2ec5918f3c721c9e070 (diff) | |
download | cpython-ea5b545e38b3fec7ff29276b5cd59dec583ebf34.zip cpython-ea5b545e38b3fec7ff29276b5cd59dec583ebf34.tar.gz cpython-ea5b545e38b3fec7ff29276b5cd59dec583ebf34.tar.bz2 |
[3.6] bpo-30696: Fix the REPL looping endlessly when no memory (GH-4160). (#4379)
(cherry picked from commit e0582a37c8d1776a2fd4968e9216f3a05f780276)
Diffstat (limited to 'Python')
-rw-r--r-- | Python/pythonrun.c | 60 |
1 files changed, 42 insertions, 18 deletions
diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 6a9722b..e644e2a 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -61,6 +61,7 @@ static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *, PyCompilerFlags *); static void err_input(perrdetail *); static void err_free(perrdetail *); +static int PyRun_InteractiveOneObjectEx(FILE *, PyObject *, PyCompilerFlags *); /* Parse input from a file and execute it */ @@ -86,6 +87,7 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename_str, PyCompilerFlags * PyObject *filename, *v; int ret, err; PyCompilerFlags local_flags; + int nomem_count = 0; filename = PyUnicode_DecodeFSDefault(filename_str); if (filename == NULL) { @@ -107,19 +109,29 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename_str, PyCompilerFlags * _PySys_SetObjectId(&PyId_ps2, v = PyUnicode_FromString("... ")); Py_XDECREF(v); } - err = -1; - for (;;) { - ret = PyRun_InteractiveOneObject(fp, filename, flags); - _PY_DEBUG_PRINT_TOTAL_REFS(); - if (ret == E_EOF) { - err = 0; - break; + err = 0; + do { + ret = PyRun_InteractiveOneObjectEx(fp, filename, flags); + if (ret == -1 && PyErr_Occurred()) { + /* Prevent an endless loop after multiple consecutive MemoryErrors + * while still allowing an interactive command to fail with a + * MemoryError. */ + if (PyErr_ExceptionMatches(PyExc_MemoryError)) { + if (++nomem_count > 16) { + PyErr_Clear(); + err = -1; + break; + } + } else { + nomem_count = 0; + } + PyErr_Print(); + flush_io(); + } else { + nomem_count = 0; } - /* - if (ret == E_NOMEM) - break; - */ - } + _PY_DEBUG_PRINT_TOTAL_REFS(); + } while (ret != E_EOF); Py_DECREF(filename); return err; } @@ -148,8 +160,11 @@ static int PARSER_FLAGS(PyCompilerFlags *flags) PyPARSE_WITH_IS_KEYWORD : 0)) : 0) #endif -int -PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags) +/* A PyRun_InteractiveOneObject() auxiliary function that does not print the + * error on failure. */ +static int +PyRun_InteractiveOneObjectEx(FILE *fp, PyObject *filename, + PyCompilerFlags *flags) { PyObject *m, *d, *v, *w, *oenc = NULL, *mod_name; mod_ty mod; @@ -161,7 +176,6 @@ PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags) mod_name = _PyUnicode_FromId(&PyId___main__); /* borrowed */ if (mod_name == NULL) { - PyErr_Print(); return -1; } @@ -221,7 +235,6 @@ PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags) PyErr_Clear(); return E_EOF; } - PyErr_Print(); return -1; } m = PyImport_AddModuleObject(mod_name); @@ -233,8 +246,6 @@ PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags) v = run_mod(mod, filename, d, d, flags, arena); PyArena_Free(arena); if (v == NULL) { - PyErr_Print(); - flush_io(); return -1; } Py_DECREF(v); @@ -243,6 +254,19 @@ PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags) } int +PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags) +{ + int res; + + res = PyRun_InteractiveOneObjectEx(fp, filename, flags); + if (res == -1) { + PyErr_Print(); + flush_io(); + } + return res; +} + +int PyRun_InteractiveOneFlags(FILE *fp, const char *filename_str, PyCompilerFlags *flags) { PyObject *filename; |