# HG changeset patch # Parent 3d6b6736174996211f8946f0626c7524fa418c04 Issue #26685: Report exceptions when garbage collecting FileIO and socket diff -r 3d6b67361749 Lib/_pyio.py --- a/Lib/_pyio.py Fri Apr 01 06:55:55 2016 +0000 +++ b/Lib/_pyio.py Mon Apr 04 01:35:31 2016 +0000 @@ -382,7 +382,7 @@ # the end users, we suppress the traceback. try: self.close() - except: + except: # ?? pass ### Inquiries ### diff -r 3d6b67361749 Lib/test/test_io.py --- a/Lib/test/test_io.py Fri Apr 01 06:55:55 2016 +0000 +++ b/Lib/test/test_io.py Mon Apr 04 01:35:31 2016 +0000 @@ -914,7 +914,7 @@ s = s.getvalue().strip() if s: # The destructor *may* have printed an unraisable error, check it - self.assertEqual(len(s.splitlines()), 1) + self.assertEqual(len(s.splitlines()), 1, repr(s)) self.assertTrue(s.startswith("Exception OSError: "), s) self.assertTrue(s.endswith(" ignored"), s) @@ -2543,7 +2543,7 @@ s = s.getvalue().strip() if s: # The destructor *may* have printed an unraisable error, check it - self.assertEqual(len(s.splitlines()), 1) + self.assertEqual(len(s.splitlines()), 1, repr(s)) self.assertTrue(s.startswith("Exception OSError: "), s) self.assertTrue(s.endswith(" ignored"), s) @@ -2950,6 +2950,7 @@ self.assertIsInstance(err.exception.__context__, NameError) self.assertIn('non_existing_flush', str(err.exception.__context__)) self.assertFalse(txt.closed) + del buffer.close # Avoid exception during garbage collection def test_multi_close(self): txt = self.TextIOWrapper(self.BytesIO(self.testdata), encoding="ascii") diff -r 3d6b67361749 Misc/NEWS --- a/Misc/NEWS Fri Apr 01 06:55:55 2016 +0000 +++ b/Misc/NEWS Mon Apr 04 01:35:31 2016 +0000 @@ -237,6 +237,9 @@ Library ------- +- Issue #26685: Report exceptions when FileIO and socket objects are garbage + collected. + - Issue #26676: Added missing XMLPullParser to ElementTree.__all__. - Issue #22854: Change BufferedReader.writable() and diff -r 3d6b67361749 Modules/_io/iobase.c --- a/Modules/_io/iobase.c Fri Apr 01 06:55:55 2016 +0000 +++ b/Modules/_io/iobase.c Mon Apr 04 01:35:31 2016 +0000 @@ -259,13 +259,9 @@ finalization process. */ if (_PyObject_SetAttrId(self, &PyId__finalizing, Py_True)) PyErr_Clear(); - res = PyObject_CallMethodObjArgs((PyObject *) self, _PyIO_str_close, - NULL); - /* Silencing I/O errors is bad, but printing spurious tracebacks is - equally as bad, and potentially more frequent (because of - shutdown issues). */ + res = PyObject_CallMethodObjArgs(self, _PyIO_str_close, NULL); if (res == NULL) - PyErr_Clear(); + PyErr_WriteUnraisable(self); else Py_DECREF(res); } diff -r 3d6b67361749 Modules/socketmodule.c --- a/Modules/socketmodule.c Fri Apr 01 06:55:55 2016 +0000 +++ b/Modules/socketmodule.c Mon Apr 04 01:35:31 2016 +0000 @@ -4182,6 +4182,7 @@ { SOCKET_T fd; PyObject *error_type, *error_value, *error_traceback; + int res; /* Save the current exception, if any. */ PyErr_Fetch(&error_type, &error_value, &error_traceback); @@ -4203,8 +4204,12 @@ /* We do not want to retry upon EINTR: see sock_close() */ Py_BEGIN_ALLOW_THREADS - (void) SOCKETCLOSE(fd); + res = SOCKETCLOSE(fd); Py_END_ALLOW_THREADS + if (res < 0) { + s->errorhandler(); + PyErr_WriteUnraisable((PyObject *)s); + } } /* Restore the saved exception. */