[IronPython] fepy socket seek

Sanghyeon Seo sanxiyn at gmail.com
Wed Nov 15 18:34:37 CET 2006


2006/11/16, Christopher Baus <christopher at baus.net>:
> Good question.  The seek must be in the binary write.  I'm not calling it
> directly.  Again, the error only occurs when the binary flag is set.  Any
> write on a socket file with the binary flag set causes a seek error.

Let's see what's going on here...

There is no socket.makefile in IronPython.

socket.makefile in FePy is implemented by creating NetworkStream from
.NET socket and "open" it using file() built-in. NetworkStream is not
seekable!

Internally, file() built-in is implemented by PythonFile class. It has
two important members, reader of type PythonStreamReader, and writer
of type PythonStreamWriter. If underlying system is not readable,
reader is null, and if it is not writable, writer is null. N.B. file
mode you pass to file() is not used.

As NetworkStream is readable and writable, reader and writer are
instantiated. Exactly which reader or writer is determined by file
mode. There are PythonBinaryReader, PythonText{CRLF,CR,LF}Reader, and
PythonUniversalReader, and they do what you can guess from the name.
There are also corresponding writers.

When you write to file,
1. writer is checked for null. If it is, stream is not writable. Raise
exception.
2. string is passed to the writer.
3. The writer does appropriate newline translation and write it.
4. The number of bytes written, after newline translation, is returned.
5. reader is checked for null. If it is, some steps are skipped.
6. reader's position is read.
7. The number of bytes written is added to the current position.
8. reader's position is set to the sum in 7 in order to syncrhonise.

6 will cause seek error if stream is not seekable. This doesn't
happen, because reader implementations maintain position by themselves
instead of reading underlying stream's position. It does read
underlying stream's position in the constructor, but only if it's
seekable. Bah, except PythonBinaryReader, that is.

So seek error is inevitable, whenever all of following conditions are met:
1. write() is called
2. underlying stream is writable
3. underlying stream is readable
4. binary reader is used
5. underlying stream is not seekable

Solution: Check if stream is seekable in PythonBinaryReader too. If
it's not seekable, it doesn't make much sense to set Position "to
synchronise" anyway.

-- 
Seo Sanghyeon



More information about the Ironpython-users mailing list