Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: AV in IdSocketHandler


This question is not answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 4 - Last Post: Apr 5, 2017 8:59 AM Last Post By: Remy Lebeau (Te... Threads: [ Previous | Next ]
Mike Collins

Posts: 46
Registered: 9/23/05
AV in IdSocketHandler  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 9, 2015 9:00 AM
Hi All,

Chasing a really annoying AV connected with DataSnap but showing up in one of the Indy(??) Id units. Wasn't sure which was the best group to post in.

I have a client connecting to a Windows DataSnap service - both are running on the same machine at the moment, using TCP/IP, 32-bit Windows 7, 32-bit binaries, XE8 C++Builder.

During authentication, the service need to communicate with a SQL database via ODBC. If this connection link is down, it eventually times out. The timeout is raised as an exception and detected in the client code, like this:

try
{
try
{
if ( dsPulseServerSnap->Connected )
dsPulseServerSnap->Close();

dsPulseServerSnap->Params->Values["HostName"] = p_wzDsAddress;
dsPulseServerSnap->Params->Values["Port"] = p_iDsPort;
dsPulseServerSnap->Params->Values["DSAuthenticationUser"] = wzUName;
dsPulseServerSnap->Params->Values["DSAuthenticationPassword"] = wzPWord;

dsPulseServerSnap->Open();
if ( dsPulseServerSnap->Connected )
{
// Create Proxy, call server method(s)
}
}
catch (const System::Sysutils::Exception &e)
{
// Converts Exception Messages to internal error codes - Timeout is caught here...
iRtn = CommsExceptionToDsError( e.Message );
}
}
__finally
{
if ( iRtn == DS_COMMS_SUCCESS )
{
// Call ok
}
}

However, when I get a time out, an AV is raised in IdSocketHandler.pas at:

procedure TIdSocketHandle.CloseSocket;
begin
if HandleAllocated then begin
FConnectionHandle.Enter; try
// Must be first, closing socket will trigger some errors, and they
// may then call (in other threads) Connected, which in turn looks at
// FHandleAllocated.
FHandleAllocated := False;
Disconnect;
SetHandle(Id_INVALID_SOCKET); <- AT THIS CALL - raised exception class $C0000005 with message 'access violation at 0x00935045: read of address 0x00000000'
finally
FConnectionHandle.Leave;
end;
end;
end;


Specifically:

procedure TIdSocketHandle.SetHandle(AHandle: TIdStackSocketHandle);
var
LOpt: Integer;
begin
if (FHandle <> Id_INVALID_SOCKET) then begin
FReadSocketList.Remove(FHandle); <- FReadSocketList has already been freed!!
end;
...

When I trace this, I find that a TIdSocketHandle is created when an attempt is made to open the DataSnap / TSQLConnection, and destroyed when the connection times out but then there is an additional call made to TIdSocketHandle.CloseSocket after the destructor is called. As a results, FReadSocketList is already freed (and NULL) and thus the AV occurs.

I can easily resolve this by modifying the SetHandle() method to check for a NULL FReadSocketList but I'm a bit reticent to start modifying this if something more fundimental is happening.

Any suggestions or tips - is this a known bug or should I report it to QC

Many thanks

Mike C

Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: AV in IdSocketHandler  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 9, 2015 10:09 AM   in response to: Mike Collins in response to: Mike Collins
Mike wrote:

When I trace this, I find that a TIdSocketHandle is created when
an attempt is made to open the DataSnap / TSQLConnection, and
destroyed when the connection times out

The TIdSocketHandle object should not be getting destroyed on a timeout error,
only when the owning TIdIOHandler object itself is destroyed.

but then there is an additional call made to TIdSocketHandle.CloseSocket
after the destructor is called.

Who is making the extra call? What does the call stack look like when the
error happens? This implies that maybe something is calling TIdIOHandler.Close()
after the IOHandler object has been destroyed.

--
Remy Lebeau (TeamB)
Mike Collins

Posts: 46
Registered: 9/23/05
Re: AV in IdSocketHandler  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 22, 2015 7:13 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
The TIdSocketHandle object should not be getting destroyed on a timeout error,
only when the owning TIdIOHandler object itself is destroyed.

Who is making the extra call? What does the call stack look like when the
error happens? This implies that maybe something is calling TIdIOHandler.Close()
after the IOHandler object has been destroyed.

Hi Remy, sorry for the late reply - got side tracked on something.

I wanted to get a reply back quickly so I have done a provisional trace and tried to capture the stack on the occasions that TIdSocketHandle.SetHandle() is called. It is by no means a complete trace but it might shed some light - if you need something more complete then please let me know.

I wasn't sure how to actually dump / save the call stack from within the IDE so I've just screen grabbed it (is there a way of doing this?).

Just to summaries, I'm running XE8, on 32-bit Windows 7, under a vmWare. The AV ONLY occurs when I am connected to a wi-fi network that requires additional logon (I only noticed it when I was connected to a wifi network in a cafe that required a logon through the browser). It does not occure when I am connected directly to a network or on an open wifi. It also does not occur when I have no network access.

1) I run my DataSnap client,

2) It tries to connect to the DataSnap service (running locally, also 32-bit, XE8 build)

3) The service tries authenticate the credentials provided in the AuthenticationManager, via an ODBC connection to a SQL server. As there is no direct network access, the server eventually times out, and I believe the Client connection then times out also (I throw specific exceptions from the OnAuthenticate event to indicate the reason for authentication failure and I'm not seeing any of them crop up).

4) [http://imgur.com/a/sG4au] gets called 3 times (1st.png, 2nd.png and 3rd_AV.png) and it is on the 3rd call the the AV occures. The other image, AV_Capture.png shows the state of the local variable.

http://imgur.com/a/sG4au

Mike
Robert Björkman

Posts: 7
Registered: 10/1/11
Re: AV in IdSocketHandler  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 5, 2017 4:31 AM   in response to: Mike Collins in response to: Mike Collins
We also stumbled upon this problem.

Seems to happen because IOHandler.Close is being called from the DBXScheduler thread at the same time the Socket is destroyed in the calling thread.

Problem was "solved" by moving the critical section to before HandleAllocated.

procedure TIdSocketHandle.CloseSocket;
begin
  FConnectionHandle.Enter;
  try
    if HandleAllocated then begin
      // Must be first, closing socket will trigger some errors, and they
      // may then call (in other threads) Connected, which in turn looks at
      // FHandleAllocated.
      FHandleAllocated := False;
      Disconnect;
      SetHandle(Id_INVALID_SOCKET);
 
    end;
  finally
    FConnectionHandle.Leave;
  end;
end;


What seems to happen is that the DBXScheduler checks HandleAllocated, and before it can enter the critical section, the IPC-thread frees the socket which in turn calls closeSocket and it goes on to enter the critical section, closes the socket and then destroys it. When the critical section is released the FReadSocketList is freed and the DBXSchedulerThread raises an AV.

Its my hypotesis anyhow. The fix above seems to be working, no idea on the performance impact of entering the critical section even if the handle is not allocated though.

T<25372>][DBXSchedulerThread]TIdSocketHandle.CloseSocket(04763BD0) 1412
T<20572>][TIPCServerThread]TestConnection: NOT connected
T<20572>][TIPCServerThread]FreeAndNil(FServer)-BEGIN
T<20572>][TIPCServerThread]TIdSocketHandle.CloseSocket(04763BD0) 1412
T<20572>][TIPCServerThread]TIdSocketHandle.Destroy(04763BD0)
T<20572>][TIPCServerThread]TIdSocketHandle.CloseSocket(04763BD0) 1412
T<25372>][DBXSchedulerThread]TIdSocketHandle.SetHandle(04763BD0) 1412 => -1
T<20572>][TIPCServerThread]FreeAndNil(FServer)-END
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: AV in IdSocketHandler  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 5, 2017 8:59 AM   in response to: Robert Björkman in response to: Robert Björkman
Robert wrote:

Problem was "solved" by moving the critical section to
before HandleAllocated.

Thanks. I have checked in that fix.

--
Remy Lebeau (TeamB)


---
This email has been checked for viruses by AVG.
http://www.avg.com

Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02