Author: Armin Rigo <ar...@tunes.org>
Branch: 
Changeset: r73922:80f6a6e5c89c
Date: 2014-10-13 19:18 +0200
http://bitbucket.org/pypy/pypy/changeset/80f6a6e5c89c/

Log:    Test and fix, likely fixes issue 1887

diff --git a/rpython/rlib/streamio.py b/rpython/rlib/streamio.py
--- a/rpython/rlib/streamio.py
+++ b/rpython/rlib/streamio.py
@@ -557,13 +557,27 @@
 
     def tell(self):
         tellpos = self.do_tell()  # This may fail
+        # Best-effort: to avoid extra system calls to tell() all the
+        # time, and a more complicated logic in this class, we can
+        # only assume that nobody changed the underlying file
+        # descriptor position while we have buffered data.  If they
+        # do, we might get bogus results here (and the following
+        # read() will still return the data cached at the old
+        # position).  Just make sure that we don't fail an assert.
         offset = len(self.buf) - self.pos
-        assert tellpos >= offset #, (locals(), self.__dict__)
+        if tellpos < offset:
+            # bug!  someone changed the fd position under our feet,
+            # and moved it at or very close to the beginning of the
+            # file, so that we have more buffered data than the
+            # current offset.
+            self.buf = ""
+            self.pos = 0
+            offset = 0
         return tellpos - offset
 
     def seek(self, offset, whence):
-        # This may fail on the do_seek() or do_tell() call.
-        # But it won't call either on a relative forward seek.
+        # This may fail on the do_seek() or on the tell() call.
+        # But it won't depend on either on a relative forward seek.
         # Nor on a seek to the very end.
         if whence == 0 or whence == 1:
             currentsize = len(self.buf) - self.pos
diff --git a/rpython/rlib/test/test_streamio.py 
b/rpython/rlib/test/test_streamio.py
--- a/rpython/rlib/test/test_streamio.py
+++ b/rpython/rlib/test/test_streamio.py
@@ -1119,6 +1119,23 @@
         assert x.read() == 'abc123456'
         x.close()
 
+    def test_seek_changed_underlying_position(self):
+        tfn = str(udir.join('seek_changed_underlying_position'))
+        fo = streamio.open_file_as_stream # shorthand
+        x = fo(tfn, 'w')
+        x.write('abc123')
+        x.close()
+
+        x = fo(tfn, 'r')
+        fd = x.try_to_find_file_descriptor()
+        assert fd >= 0
+        got = x.read(1)
+        assert got == 'a'
+        assert x.tell() == 1
+        os.lseek(fd, 0, 0)
+        assert x.tell() == 0    # detected in this case.  not always.
+        # the point of the test is that we don't crash in an assert.
+
 
 # Speed test
 
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to