@@ -61,6 +61,7 @@ static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *,
61
61
PyCompilerFlags * );
62
62
static void err_input (perrdetail * );
63
63
static void err_free (perrdetail * );
64
+ static int PyRun_InteractiveOneObjectEx (FILE * , PyObject * , PyCompilerFlags * );
64
65
65
66
/* Parse input from a file and execute it */
66
67
@@ -86,6 +87,7 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename_str, PyCompilerFlags *
86
87
PyObject * filename , * v ;
87
88
int ret , err ;
88
89
PyCompilerFlags local_flags ;
90
+ int nomem_count = 0 ;
89
91
90
92
filename = PyUnicode_DecodeFSDefault (filename_str );
91
93
if (filename == NULL ) {
@@ -107,19 +109,29 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename_str, PyCompilerFlags *
107
109
_PySys_SetObjectId (& PyId_ps2 , v = PyUnicode_FromString ("... " ));
108
110
Py_XDECREF (v );
109
111
}
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 ;
117
132
}
118
- /*
119
- if (ret == E_NOMEM)
120
- break;
121
- */
122
- }
133
+ _PY_DEBUG_PRINT_TOTAL_REFS ();
134
+ } while (ret != E_EOF );
123
135
Py_DECREF (filename );
124
136
return err ;
125
137
}
@@ -148,8 +160,11 @@ static int PARSER_FLAGS(PyCompilerFlags *flags)
148
160
PyPARSE_WITH_IS_KEYWORD : 0)) : 0)
149
161
#endif
150
162
151
- 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 )
153
168
{
154
169
PyObject * m , * d , * v , * w , * oenc = NULL , * mod_name ;
155
170
mod_ty mod ;
@@ -161,7 +176,6 @@ PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags)
161
176
162
177
mod_name = _PyUnicode_FromId (& PyId___main__ ); /* borrowed */
163
178
if (mod_name == NULL ) {
164
- PyErr_Print ();
165
179
return -1 ;
166
180
}
167
181
@@ -221,7 +235,6 @@ PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags)
221
235
PyErr_Clear ();
222
236
return E_EOF ;
223
237
}
224
- PyErr_Print ();
225
238
return -1 ;
226
239
}
227
240
m = PyImport_AddModuleObject (mod_name );
@@ -233,15 +246,26 @@ PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags)
233
246
v = run_mod (mod , filename , d , d , flags , arena );
234
247
PyArena_Free (arena );
235
248
if (v == NULL ) {
236
- PyErr_Print ();
237
- flush_io ();
238
249
return -1 ;
239
250
}
240
251
Py_DECREF (v );
241
252
flush_io ();
242
253
return 0 ;
243
254
}
244
255
256
+ 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
+
245
269
int
246
270
PyRun_InteractiveOneFlags (FILE * fp , const char * filename_str , PyCompilerFlags * flags )
247
271
{
0 commit comments