comparison Python/pythonrun.c @ 73761:150e096095e5 3.2

Issue #13444: When stdout has been closed explicitly, we should not attempt to flush it at shutdown and print an error. This also adds a test for issue #5319, whose resolution introduced the issue.
author Antoine Pitrou <solipsis@pitrou.net>
date Sat, 26 Nov 2011 21:59:36 +0100
parents 7a48e98915f2
children f15943505db0 37300a1df7d7
comparison
equal deleted inserted replaced
73759:7097d52cacee 73761:150e096095e5
330 extern void dump_counts(FILE*); 330 extern void dump_counts(FILE*);
331 #endif 331 #endif
332 332
333 /* Flush stdout and stderr */ 333 /* Flush stdout and stderr */
334 334
335 static int
336 file_is_closed(PyObject *fobj)
337 {
338 int r;
339 PyObject *tmp = PyObject_GetAttrString(fobj, "closed");
340 if (tmp == NULL) {
341 PyErr_Clear();
342 return 0;
343 }
344 r = PyObject_IsTrue(tmp);
345 Py_DECREF(tmp);
346 if (r < 0)
347 PyErr_Clear();
348 return r > 0;
349 }
350
335 static void 351 static void
336 flush_std_files(void) 352 flush_std_files(void)
337 { 353 {
338 PyObject *fout = PySys_GetObject("stdout"); 354 PyObject *fout = PySys_GetObject("stdout");
339 PyObject *ferr = PySys_GetObject("stderr"); 355 PyObject *ferr = PySys_GetObject("stderr");
340 PyObject *tmp; 356 PyObject *tmp;
341 357
342 if (fout != NULL && fout != Py_None) { 358 if (fout != NULL && fout != Py_None && !file_is_closed(fout)) {
343 tmp = PyObject_CallMethod(fout, "flush", ""); 359 tmp = PyObject_CallMethod(fout, "flush", "");
344 if (tmp == NULL) 360 if (tmp == NULL)
345 PyErr_WriteUnraisable(fout); 361 PyErr_WriteUnraisable(fout);
346 else 362 else
347 Py_DECREF(tmp); 363 Py_DECREF(tmp);
348 } 364 }
349 365
350 if (ferr != NULL && ferr != Py_None) { 366 if (ferr != NULL && ferr != Py_None && !file_is_closed(ferr)) {
351 tmp = PyObject_CallMethod(ferr, "flush", ""); 367 tmp = PyObject_CallMethod(ferr, "flush", "");
352 if (tmp == NULL) 368 if (tmp == NULL)
353 PyErr_Clear(); 369 PyErr_Clear();
354 else 370 else
355 Py_DECREF(tmp); 371 Py_DECREF(tmp);