[pypy-commit] pypy default: CPython issue #5700: flush() was not called in close() if closefd=False.

amauryfa noreply at buildbot.pypy.org
Sun Jun 14 16:38:07 CEST 2015


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: 
Changeset: r78089:c7298ea71c4d
Date: 2015-06-14 16:01 +0200
http://bitbucket.org/pypy/pypy/changeset/c7298ea71c4d/

Log:	CPython issue #5700: flush() was not called in close() if
	closefd=False.

diff --git a/pypy/module/_io/interp_fileio.py b/pypy/module/_io/interp_fileio.py
--- a/pypy/module/_io/interp_fileio.py
+++ b/pypy/module/_io/interp_fileio.py
@@ -242,11 +242,18 @@
                                exception_name='w_IOError')
 
     def close_w(self, space):
+        try:
+            W_RawIOBase.close_w(self, space)
+        except OperationError:
+            if not self.closefd:
+                self.fd = -1
+                raise
+            self._close(space)
+            raise
         if not self.closefd:
             self.fd = -1
             return
         self._close(space)
-        W_RawIOBase.close_w(self, space)
 
     def _dircheck(self, space, w_filename):
         # On Unix, fopen will succeed for directories.
diff --git a/pypy/module/_io/test/test_fileio.py b/pypy/module/_io/test/test_fileio.py
--- a/pypy/module/_io/test/test_fileio.py
+++ b/pypy/module/_io/test/test_fileio.py
@@ -209,6 +209,22 @@
             if os.path.exists(self.tmpfile):
                 os.unlink(self.tmpfile)
 
+    def test_flush_error_on_close(self):
+        # Test that the file is closed despite failed flush
+        # and that flush() is called before file closed.
+        import _io, os
+        fd = os.open(self.tmpfile, os.O_RDONLY, 0666)
+        f = _io.FileIO(fd, 'r', closefd=False)
+        closed = []
+        def bad_flush():
+            closed[:] = [f.closed]
+            raise IOError()
+        f.flush = bad_flush
+        raises(IOError, f.close) # exception not swallowed
+        assert f.closed
+        assert closed         # flush() called
+        assert not closed[0]  # flush() called before file closed
+        os.close(fd)
 
 def test_flush_at_exit():
     from pypy import conftest


More information about the pypy-commit mailing list