[3.6] bpo-30696: Fix the REPL looping endlessly when no memory (GH-41… · python/cpython@ea5b545
@@ -61,6 +61,7 @@ static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *,
6161PyCompilerFlags *);
6262static void err_input(perrdetail *);
6363static void err_free(perrdetail *);
64+static int PyRun_InteractiveOneObjectEx(FILE *, PyObject *, PyCompilerFlags *);
64656566/* Parse input from a file and execute it */
6667@@ -86,6 +87,7 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename_str, PyCompilerFlags *
8687PyObject *filename, *v;
8788int ret, err;
8889PyCompilerFlags local_flags;
90+int nomem_count = 0;
89919092filename = PyUnicode_DecodeFSDefault(filename_str);
9193if (filename == NULL) {
@@ -107,19 +109,29 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename_str, PyCompilerFlags *
107109_PySys_SetObjectId(&PyId_ps2, v = PyUnicode_FromString("... "));
108110Py_XDECREF(v);
109111 }
110-err = -1;
111-for (;;) {
112-ret = PyRun_InteractiveOneObject(fp, filename, flags);
113-_PY_DEBUG_PRINT_TOTAL_REFS();
114-if (ret == E_EOF) {
115-err = 0;
116-break;
112+err = 0;
113+do {
114+ret = PyRun_InteractiveOneObjectEx(fp, filename, flags);
115+if (ret == -1 && PyErr_Occurred()) {
116+/* Prevent an endless loop after multiple consecutive MemoryErrors
117+ * while still allowing an interactive command to fail with a
118+ * MemoryError. */
119+if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
120+if (++nomem_count > 16) {
121+PyErr_Clear();
122+err = -1;
123+break;
124+ }
125+ } else {
126+nomem_count = 0;
127+ }
128+PyErr_Print();
129+flush_io();
130+ } else {
131+nomem_count = 0;
117132 }
118-/*
119- if (ret == E_NOMEM)
120- break;
121- */
122- }
133+_PY_DEBUG_PRINT_TOTAL_REFS();
134+ } while (ret != E_EOF);
123135Py_DECREF(filename);
124136return err;
125137}
@@ -148,8 +160,11 @@ static int PARSER_FLAGS(PyCompilerFlags *flags)
148160 PyPARSE_WITH_IS_KEYWORD : 0)) : 0)
149161#endif
150162151-int
152-PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags)
163+/* A PyRun_InteractiveOneObject() auxiliary function that does not print the
164+ * error on failure. */
165+static int
166+PyRun_InteractiveOneObjectEx(FILE *fp, PyObject *filename,
167+PyCompilerFlags *flags)
153168{
154169PyObject *m, *d, *v, *w, *oenc = NULL, *mod_name;
155170mod_ty mod;
@@ -161,7 +176,6 @@ PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags)
161176162177mod_name = _PyUnicode_FromId(&PyId___main__); /* borrowed */
163178if (mod_name == NULL) {
164-PyErr_Print();
165179return -1;
166180 }
167181@@ -221,7 +235,6 @@ PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags)
221235PyErr_Clear();
222236return E_EOF;
223237 }
224-PyErr_Print();
225238return -1;
226239 }
227240m = PyImport_AddModuleObject(mod_name);
@@ -233,15 +246,26 @@ PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags)
233246v = run_mod(mod, filename, d, d, flags, arena);
234247PyArena_Free(arena);
235248if (v == NULL) {
236-PyErr_Print();
237-flush_io();
238249return -1;
239250 }
240251Py_DECREF(v);
241252flush_io();
242253return 0;
243254}
244255256+int
257+PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags)
258+{
259+int res;
260+261+res = PyRun_InteractiveOneObjectEx(fp, filename, flags);
262+if (res == -1) {
263+PyErr_Print();
264+flush_io();
265+ }
266+return res;
267+}
268+245269int
246270PyRun_InteractiveOneFlags(FILE *fp, const char *filename_str, PyCompilerFlags *flags)
247271{