File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -272,6 +272,25 @@ def test_unmached_quote(self):
272272 self .assertRegex (err .decode ('ascii' , 'ignore' ), 'SyntaxError' )
273273 self .assertEqual (b'' , out )
274274
275+ def test_stdout_flush_at_shutdown (self ):
276+ # Issue #5319: if stdout.flush() fails at shutdown, an error should
277+ # be printed out.
278+ code = """if 1:
279+ import os, sys
280+ sys.stdout.write('x')
281+ os.close(sys.stdout.fileno())"""
282+ rc , out , err = assert_python_ok ('-c' , code )
283+ self .assertEqual (b'' , out )
284+ self .assertRegex (err .decode ('ascii' , 'ignore' ),
285+ 'Exception IOError: .* ignored' )
286+
287+ def test_closed_stdout (self ):
288+ # Issue #13444: if stdout has been explicitly closed, we should
289+ # not attempt to flush it at shutdown.
290+ code = "import sys; sys.stdout.close()"
291+ rc , out , err = assert_python_ok ('-c' , code )
292+ self .assertEqual (b'' , err )
293+
275294
276295def test_main ():
277296 test .support .run_unittest (CmdLineTest )
Original file line number Diff line number Diff line change @@ -83,6 +83,9 @@ Core and Builtins
8383Library
8484-------
8585
86+ - Issue #13444: When stdout has been closed explicitly, we should not attempt
87+ to flush it at shutdown and print an error.
88+
8689- Issue #12856: Ensure child processes do not inherit the parent's random
8790 seed for filename generation in the tempfile module. Patch by Brian
8891 Harring.
Original file line number Diff line number Diff line change @@ -332,22 +332,38 @@ extern void dump_counts(FILE*);
332332
333333/* Flush stdout and stderr */
334334
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+
335351static void
336352flush_std_files (void )
337353{
338354 PyObject * fout = PySys_GetObject ("stdout" );
339355 PyObject * ferr = PySys_GetObject ("stderr" );
340356 PyObject * tmp ;
341357
342- if (fout != NULL && fout != Py_None ) {
358+ if (fout != NULL && fout != Py_None && ! file_is_closed ( fout ) ) {
343359 tmp = PyObject_CallMethod (fout , "flush" , "" );
344360 if (tmp == NULL )
345361 PyErr_WriteUnraisable (fout );
346362 else
347363 Py_DECREF (tmp );
348364 }
349365
350- if (ferr != NULL && ferr != Py_None ) {
366+ if (ferr != NULL && ferr != Py_None && ! file_is_closed ( ferr ) ) {
351367 tmp = PyObject_CallMethod (ferr , "flush" , "" );
352368 if (tmp == NULL )
353369 PyErr_Clear ();
You can’t perform that action at this time.
0 commit comments