[pypy-commit] pypy default: Improve the error message when file.__del__() fails

arigo noreply at buildbot.pypy.org
Wed May 25 20:36:55 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r44485:ded93b2eecd9
Date: 2011-05-25 20:48 +0200
http://bitbucket.org/pypy/pypy/changeset/ded93b2eecd9/

Log:	Improve the error message when file.__del__() fails in closing the
	descriptor.

diff --git a/pypy/module/_file/interp_file.py b/pypy/module/_file/interp_file.py
--- a/pypy/module/_file/interp_file.py
+++ b/pypy/module/_file/interp_file.py
@@ -43,7 +43,11 @@
         # assume that the file and stream objects are only visible in the
         # thread that runs __del__, so no race condition should be possible
         self.clear_all_weakrefs()
-        self.direct_close()
+        try:
+            self.direct_close()
+        except StreamErrors, e:
+            operr = wrap_streamerror(self.space, e, self.w_name)
+            operr.write_unraisable(self.space, '__del__ of ', self)
 
     def fdopenstream(self, stream, fd, mode, w_name=None):
         self.fd = fd
@@ -553,4 +557,4 @@
 @unwrap_spec(file=W_File, encoding="str_or_None", errors="str_or_None")
 def set_file_encoding(space, file, encoding=None, errors=None):
     file.encoding = encoding
-    file.errors = errors
\ No newline at end of file
+    file.errors = errors
diff --git a/pypy/module/_file/test/test_file.py b/pypy/module/_file/test/test_file.py
--- a/pypy/module/_file/test/test_file.py
+++ b/pypy/module/_file/test/test_file.py
@@ -232,6 +232,29 @@
             data = f.read()
             assert data == "15"
 
+    def test_exception_from_close(self):
+        import os
+        f = self.file(self.temppath, 'w')
+        os.close(f.fileno())
+        raises(IOError, f.close)    # bad file descriptor
+
+    def test_exception_from_del(self):
+        import os, gc, sys, cStringIO
+        f = self.file(self.temppath, 'w')
+        g = cStringIO.StringIO()
+        preverr = sys.stderr
+        try:
+            sys.stderr = g
+            os.close(f.fileno())
+            del f
+            gc.collect()     # bad file descriptor in f.__del__()
+        finally:
+            sys.stderr = preverr
+        import errno
+        assert os.strerror(errno.EBADF) in g.getvalue()
+        # the following is a "nice to have" feature that CPython doesn't have
+        if '__pypy__' in sys.builtin_module_names:
+            assert self.temppath in g.getvalue()
 
 
 class AppTestConcurrency(object):


More information about the pypy-commit mailing list