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