[pypy-commit] pypy default: Test and fix, likely fixes issue 1887
arigo
noreply at buildbot.pypy.org
Mon Oct 13 19:18:30 CEST 2014
Author: Armin Rigo <arigo at 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
More information about the pypy-commit
mailing list