[Python-checkins] r68640 - in sandbox/trunk/io-c: _bufferedio.c _textio.c test_io.py

antoine.pitrou python-checkins at python.org
Sat Jan 17 01:46:30 CET 2009


Author: antoine.pitrou
Date: Sat Jan 17 01:46:30 2009
New Revision: 68640

Log:
deallocating a Buffered or Text IO object could clear the err status



Modified:
   sandbox/trunk/io-c/_bufferedio.c
   sandbox/trunk/io-c/_textio.c
   sandbox/trunk/io-c/test_io.py

Modified: sandbox/trunk/io-c/_bufferedio.c
==============================================================================
--- sandbox/trunk/io-c/_bufferedio.c	(original)
+++ sandbox/trunk/io-c/_bufferedio.c	Sat Jan 17 01:46:30 2009
@@ -226,6 +226,8 @@
     PyObject *res;
     /* XXX this is inelegant */
     if (Py_TYPE(self)->tp_del == NULL) {
+        PyObject *tp, *v, *tb;
+        PyErr_Fetch(&tp, &v, &tb);
         /* We need to resurrect the object as calling close() can invoke
            arbitrary code. */
         ((PyObject *) self)->ob_refcnt++;
@@ -237,6 +239,7 @@
             PyErr_Clear();
         }
         Py_XDECREF(res);
+        PyErr_Restore(tp, v, tb);
         if (--((PyObject *) self)->ob_refcnt != 0)
             return;
     }

Modified: sandbox/trunk/io-c/_textio.c
==============================================================================
--- sandbox/trunk/io-c/_textio.c	(original)
+++ sandbox/trunk/io-c/_textio.c	Sat Jan 17 01:46:30 2009
@@ -767,6 +767,8 @@
     PyObject *res;
     /* XXX this is inelegant */
     if (Py_TYPE(self)->tp_del == NULL && self->ok) {
+        PyObject *tp, *v, *tb;
+        PyErr_Fetch(&tp, &v, &tb);
         /* We need to resurrect the object as calling close() can invoke
            arbitrary code. */
         ((PyObject *) self)->ob_refcnt++;
@@ -778,6 +780,7 @@
             PyErr_Clear();
         }
         Py_XDECREF(res);
+        PyErr_Restore(tp, v, tb);
         if (--((PyObject *) self)->ob_refcnt != 0)
             return;
     }

Modified: sandbox/trunk/io-c/test_io.py
==============================================================================
--- sandbox/trunk/io-c/test_io.py	(original)
+++ sandbox/trunk/io-c/test_io.py	Sat Jan 17 01:46:30 2009
@@ -97,6 +97,12 @@
     def readinto(self, buf):
         MockRawIO.readinto(self, buf)
         return len(buf) * 5
+    
+
+class CloseFailureIO(MockRawIO):
+
+    def close(self):
+        raise IOError
 
 
 class MockFileIO(io.BytesIO):
@@ -495,6 +501,14 @@
         # bufio should now be closed, and using it a second time should raise
         # a ValueError.
         self.assertRaises(ValueError, _with)
+    
+    def testErrorThroughDestructor(self):
+        # Test that the exception state is not modified by a destructor,
+        # even if close() fails.
+        rawio = CloseFailureIO()
+        def f():
+            self.tp(rawio).xyzzy
+        self.assertRaises(AttributeError, f)
 
 
 class BufferedReaderTest(unittest.TestCase, CommonBufferedTests):
@@ -1333,6 +1347,14 @@
         del t
         self.assertEqual(record, [1, 2, 3])
 
+    def testErrorThroughDestructor(self):
+        # Test that the exception state is not modified by a destructor,
+        # even if close() fails.
+        rawio = CloseFailureIO()
+        def f():
+            io.TextIOWrapper(rawio).xyzzy
+        self.assertRaises(AttributeError, f)
+
     # Systematic tests of the text I/O API
 
     def testBasicIO(self):


More information about the Python-checkins mailing list