summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorxdegaye <xdegaye@gmail.com>2017-11-12 16:33:16 (GMT)
committerGitHub <noreply@github.com>2017-11-12 16:33:16 (GMT)
commitea5b545e38b3fec7ff29276b5cd59dec583ebf34 (patch)
tree4916695b3b105810c0910fc129274e5dce35bc95 /Python
parent4e09deb127013f7cd097f2ec5918f3c721c9e070 (diff)
downloadcpython-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.c60
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;