Newsgroups : Borland : borland.public.delphi.internet.winsock : 2007 Nov : Re: Input Buffer empty
| Subject: | Re: Input Buffer empty |
| Posted by: | "Larry Killen" (lkill..@charter.net) |
| Date: | Wed, 5 Dec 2007 19:51:48 |
Okay, I'll do the dance again.
Here is the call stack leading up to the exception....
ReadOutfeedGSE.TReadingOutfeedThread.Execute <= Call stack
procedure TReadingOutfeedThread.Execute; <= procedure (last of my code)
begin
while not Terminated do
begin
FConn.IOHandler.WaitFor(chr(2));
FBuffer := FConn.IOHandler.ReadLn(chr(3));
ProcessData;
end;
end;
IdIOHandler.WaitFor(#2,True,False,en7Bit) <= Call stack
function TIdIOHandler.WaitFor(const AString: string; ARemoveFromBuffer:
Boolean = True; <= procedure
AInclusive: Boolean = False; const AEncoding: TIdEncoding = en7Bit):
string;
//TODO: Add a time out (default to infinite) and event to pass data
//TODO: Add a max size argument as well.
//TODO: Add a case insensitive option
var
LBytes: TIdBytes;
LPos: Integer;
begin
Result := '';
LBytes := ToBytes(AString, AEncoding);
LPos := 0;
repeat
if CheckForDataOnSource(250) then begin
LPos := InputBuffer.IndexOf(LBytes, LPos);
if LPos <> -1 then begin
if ARemoveFromBuffer and AInclusive then begin
Result := InputBuffer.Extract(LPos+Length(LBytes), AEncoding);
end else begin
if AInclusive then begin
Result := InputBuffer.Extract(LPos, AEncoding) + AString;
end else begin
Result := InputBuffer.Extract(LPos, AEncoding);
end;
if ARemoveFromBuffer then begin
InputBuffer.Remove(Length(LBytes));
end;
end;
Break;
end;
LPos := IndyMax(0, InputBuffer.Size - (Length(LBytes)-1));
end;
CheckForDisconnect;
until False;
end;
TIdIOHandler.CheckForDataOnSource(0) <= Call stack
function TIdIOHandler.CheckForDataOnSource(ATimeout: Integer = 0): Boolean;
<= procedure
begin
// return whether at least 1 byte was received
Result := False;
if Connected then begin
Result := ReadFromSource(False, ATimeout, False) > 0;
end;
end;
IdIOHandler.ReadFromSource(False,250,False) <== Call Stack
function TIdIOHandler.ReadFromSource(ARaiseExceptionIfDisconnected: Boolean;
<== Related Procedure
ATimeout: Integer; ARaiseExceptionOnTimeout: Boolean): Integer;
var
LByteCount: Integer;
LLastError: Integer;
LBuffer: TIdBytes;
begin
if ATimeout = IdTimeoutDefault then begin
// MtW: check for 0 too, for compatibility
if (ReadTimeout = IdTimeoutDefault) or (ReadTimeout = 0) then begin
ATimeout := IdTimeoutInfinite;
end else begin
ATimeout := ReadTimeout;
end;
end;
Result := 0;
// Check here as this side may have closed the socket
CheckForDisconnect(ARaiseExceptionIfDisconnected);
if SourceIsAvailable then begin
LByteCount := 0;
repeat
if Readable(ATimeout) then begin
if Opened then begin
// No need to call AntiFreeze, the Readable does that.
if SourceIsAvailable then begin
// TODO: Whey are we reallocating LBuffer every time? This
should
// be a one time operation per connection.
SetLength(LBuffer, RecvBufferSize); try
LByteCount := ReadDataFromSource(LBuffer);
if LByteCount > 0 then begin
SetLength(LBuffer, LByteCount);
if Intercept <> nil then begin
Intercept.Receive(LBuffer);
LByteCount := Length(LBuffer);
end;
//AsciiFilter - needs to go in TIdIOHandler base class
// if ASCIIFilter then begin
// for i := 1 to IOHandler.RecvBuffer.Size do begin
// PChar(IOHandler.RecvBuffer.Memory)[i] :=
Chr(Ord(PChar(IOHandler.RecvBuffer.Memory)[i]) and $7F);
// end;
// end;
// Pass through LBuffer first so it can go through Intercept
//TODO: If not intercept, we can skip this step
InputBuffer.Write(LBuffer);
end;
finally LBuffer := nil; end;
end else begin
EIdClosedSocket.Toss(RSStatusDisconnected);
end;
end else begin
LByteCount := 0;
EIdNotConnected.IfTrue(ARaiseExceptionIfDisconnected,
RSNotConnected);
end;
if LByteCount < 0 then
begin
LLastError := GStack.CheckForSocketError(LByteCount,
[Id_WSAESHUTDOWN, Id_WSAECONNABORTED]);
FClosedGracefully := True;
Close;
// Do not raise unless all data has been read by the user
if InputBufferIsEmpty then begin
GStack.RaiseSocketError(LLastError);
end;
LByteCount := 0;
end;
if LByteCount = 0 then begin
FClosedGracefully := True;
end;
// Check here as other side may have closed connection
CheckForDisconnect(ARaiseExceptionIfDisconnected);
Result := LByteCount;
end else begin
// Timeout
EIdReadTimeout.IfTrue(ARaiseExceptionOnTimeout, RSReadTimeout);
Result := -1;
Break;
end;
until (LByteCount <> 0) or (not SourceIsAvailable);
end
else if ARaiseExceptionIfDisconnected then begin
raise EIdException.Create(RSNotConnected);
end;
end;
IdIOHandlerStack.TIdIOHandlerStack.CheckForDisconnect(False, True)<== Call
Stack
procedure TIdIOHandlerStack.CheckForDisconnect( <<==Related Procedure
ARaiseExceptionIfDisconnected: Boolean; AIgnoreBuffer: Boolean);
var
LDisconnected: Boolean;
begin
// ClosedGracefully // Server disconnected
// IOHandler = nil // Client disconnected
if ClosedGracefully then begin
if BindingAllocated then begin
Close;
// Call event handlers to inform the user that we were disconnected
DoStatus(hsDisconnected);
//DoOnDisconnected;
end;
LDisconnected := True;
end else begin
LDisconnected := not BindingAllocated;
end;
// Do not raise unless all data has been read by the user
if LDisconnected then begin
if (InputBufferIsEmpty or AIgnoreBuffer) and
ARaiseExceptionIfDisconnected then begin
RaiseConnClosedGracefully;
end;
end;
end;
IdIOHandler.TIdIOHandler.InputBufferIsEmpty <<== Call stack
function TIdIOHandler.InputBufferIsEmpty: Boolean; <<== related procedure
begin
Result := FInputBuffer.Size = 0;
end;
and then the raised exception
AND THAT IS EXACTLY WHAT I AM SEEING!!
"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message
news:4747205b@newsgroups.borland.com...
>
> "Larry Killen" <lkillen@charter.net> wrote in message
> news:4745f63a$1@newsgroups.borland.com...
>
>> I recently started getting occasional InputBufferIsEmpty exceptions.
>
> There are no exceptions for that function.
>
> What exactly are you seeing?
>
>> Below is the procedure I use to read the socket. I don't
>> know how it could be empty since it is triggered by data.
>
> No, it is not. It is triggered by a continuous loop that has nothing to
> do
> with whether data is actually avalable or not.
>
>
> Gambit