Re: Bug in TIdIOHandler.ReadStream (Indy10)

Giganews Newsgroups
Subject: Re: Bug in TIdIOHandler.ReadStream (Indy10)
Posted by:  Remy Lebeau (TeamB) (no.spam@no.spam.com)
Date: Mon, 1 May 2006

"Tim Bates" <tim.bat…@cispl.com.au> wrote in message
news:17BA4DD2C1F6E240tim.bat…@cispl.com.au...

> I think I have found a subtle bug in TIdIOHandler.ReadStream
(Core/IdIOHandler.pas rev 1.97).

You are referring to a version of the file that is almost 2 years old.  1.97
is dated 5/29/04.  The last commented revision is 1.123 dated 2/8/05.  After
that, the Indy developers switched their source control system from
TeamCoherence to StarTeam, which does not place comments in the files
anymore.  Since 2/8/05, there have been 51 more revisions of
IdIOHandler.pas.  You need to upgrade before you report bugs for outdated
versions.

> The client (also using Indy10) calls
>  IOHandler.Write(Stream, 0);
> and then immediately disconnects the TIdTCPClient object. The server calls
>  IOHandler.ReadStream(Stream, FileSize, False);
> but loses the last few bytes of the file, especially on large files.
>
> I think what is happening is that inside TIdIOHandler.ReadStream
> there is a loop that looks like this:
> while Connected and (LWorkCount > 0) do begin

As it should be.  The Connected() method does not return False while there
is still pending data to be read from the socket.  Even if the client
disconnects, Connected() will continue to return True while there is still
data in the socket or the IOHandler's InputBuffer.  When the client
disconnects, if there is still data in the socket, the socket will allow
that data to be read before then reporting that the connection is
disconnected.  As long as data is read from the socket, it gets placed into
the InputBuffer for the higher-level reading methods to use.  Only when a
reading operation cannot be satisfied due to unavailable data that will
never arrive does the reading then complete, throwing an exception if
necessary.

> The actual write to the Flash card (via a TFileStream object) must
> be happening in a separate thread to the read from the socket.

It does not sound like you are managing the stream properly in the first
place.  A thread can't read from the stream at the same time that the socket
is still writing to it in another thread.  That is a very quick way to
completely corrupt the stream object.  If you really want multithreaded
streamable data, then you should write your own TStream class that writes
data directly to the Flash card in its overriden Write() method.  That way,
you can pass your custom stream to ReadStream(), and it will write data to
the Flash card immediately when ReadStream() writes the data to the stream
Just make sure that you provide adequate thread-safe synchronization for the
stream's internal buffer(s) that you implement.

> once the client disconnects, the socket code sets
> Connected := false and this immediately stops this loop

See above.

> Can someone with the appropriate authority please add this to the Indy bug
system?

No, because it is not an Indy bug to begin with.

Gambit

Replies

None

In response to

Bug in TIdIOHandler.ReadStream (Indy10) posted by Tim Bates on Mon, 1 May 2006