[DUG] SocketConnection in D6

Ross Levis ross at stationplaylist.com
Mon Dec 19 16:34:03 NZDT 2005


I also use these old controls (in D7) and have had an odd AV from 
TSocketConnection when closing the program, but it's been so rare that 
I've never bothered spending any time on it.  Thanks for the fix.

Ross.

----- Original Message ----- 
From: "Chocolate Fish Software" <ChocFish at xtra.co.nz>
To: "'NZ Borland Developers Group - Delphi List'" <delphi at ns3.123.co.nz>
Sent: Monday, December 19, 2005 4:08 PM
Subject: [DUG] SocketConnection in D6


Anyone else run into the TSocketConnection bug in D6 that causes access
violations and/or other errors when you disconnect or free the thing? 
If
you're using TSocketConnections but not explicitly closing them then 
you'll
get intermittent errors when your program ends, so if you sometimes get 
AVs
on exit then this might explain it.  I've encountered them on and off 
but
it's only now that I've tried FastMM that I've been able to pinpoint 
what
was going on.  It's TSocketTransport that's screwed (in D6).

The essence of the error is that when a socketconnection closes, its
transport thread closes its sockettransport (which frees the socket) 
through
its ITransport interface, which then falls out of scope, freeing the
sockettransport (it's an interfaced object) and in doing so, closing the
(now invalid) socket and freeing that... again.  Oops.  This error would
probably have been picked up before if it hadn't been happening within a
destructor in a thread other than the main thread.

To fix the error, create your own descendant of TSocketConnection to use
instead, as follows:

uses
  Windows, Messages, SysUtils, Classes, DB, DBClient, MConnect, 
SConnect,
  MidConst, RTLConsts;

type
  TcfSocketTransport = class(TSocketTransport, ITransport)
  protected
    { ITransport overrides }
    function GetWaitEvent: THandle; stdcall;
    procedure SetConnected(AValue: Boolean); stdcall;
  end;

  TcfSocketConnection = class(TSocketConnection)
  protected
    function CreateTransport: ITransport; override;
  end;

implementation

{ TcfSocketConnection }

function TcfSocketConnection.CreateTransport: ITransport;
var
  LSocketTransport: TcfSocketTransport;
begin
  if SupportCallbacks then
    if not LoadWinSock2 then raise Exception.CreateRes(@SNoWinSock2);
  if (Address = '') and (Host = '') then
    raise ESocketConnectionError.CreateRes(@SNoAddress);
  LSocketTransport := TcfSocketTransport.Create;
  LSocketTransport.Host := Host;
  LSocketTransport.Address := Address;
  LSocketTransport.Port := Port;
  LSocketTransport.InterceptGUID := InterceptGUID;
  Result := LSocketTransport as ITransport;
end;

{ TcfSocketTransport }

function TcfSocketTransport.GetWaitEvent: THandle;
begin
  if Assigned(Socket) then
  begin
    Result := inherited GetWaitEvent;
  end
  else Result := 0;
end;

procedure TcfSocketTransport.SetConnected(AValue: Boolean);
begin
  if not AValue and not Assigned(Socket) then Exit;
  inherited SetConnected(AValue);
  if not AValue then
    Socket := nil;
end;

Cheers,
Carl

_______________________________________________
Delphi mailing list
Delphi at ns3.123.co.nz
http://ns3.123.co.nz/mailman/listinfo/delphi



More information about the Delphi mailing list