Watch, Follow, &
Connect with Us
Public Report
Report From: Delphi-BCB/Midas/TWebConnection    [ Add a report in this area ]  
Report #:  2297   Status: Closed
after making AppServer call, setting connected to false doesn't release server
Project:  Delphi Build #:  6.0.6.163
Version:    6.0 Submitted By:   Richard Werning
Report Type:  Minor failure / Design problem Date Reported:  9/6/2002 4:12:54 PM
Severity:    Serious / Highly visible problem Last Updated: 3/20/2012 2:24:39 AM
Platform:    All versions Internal Tracking #:   153582
Resolution: Fixed (Resolution Comments) Resolved in Build: : 9.0.1761.24408
Duplicate of:  None
Voting and Rating
Overall Rating: (6 Total Ratings)
5.00 out of 5
Total Votes: 1
Description
When using TWebConnection, if you make a method call via AppServer, when you set the WebConn to false or shutdown the client,  httpsrvr.dll never releases the resources for the server, so the server continues running.

ie:
  WebConn.Connected := true;
  WebConn.AppServer.TestSomething;
  WebConn.Connected := False;


This problem exists in Delphi 5.01, Delphi 6.02, and as far as I know Delphi 7.

This is a HUGE problem for us as we use Runtime packages so that we can reference the connection inside of DLL's.  Since sConnect is in a runtime package, and we can't recompile them - we're stuck.
Steps to Reproduce:
Very simple test to prove the case.  You need a client and server, connected with TWebConnection.  Add a simple method call to the server.

If you do a straight test like:

  WebConn.Connected := true;
  WebConn.Connected := False;

The server starts up and shuts down properly.  This also holds true if you only use TClientDatasets reading from the servers DatasetProvider.

However, if you do a method call like:

  WebConn.Connected := true;
  WebConn.AppServer.TestSomething;
  WebConn.Connected := False;

Then the server will not shut down as expected.  

The reason for this is that is a sequence error in the disconnect code in sConnect.pas for TWebConnection.

- TStreamedConnection.DoDisconnect calls  InternalClose.  
- TStreamedConnection.InternalClose sets FTransIntf.connected := false, then nil
- Next TDataDispatch.Destroy runs and try's calling FInterpreter.CallFreeObject(FDispatchIndex)
- CallFreeObject calls TStreamedConnection.Send which checks FTransIntf (which is now nil), so it never calls the SendData
Workarounds
Added early exit

Need to modify sConnect.pas

  TWebConnection = class(TStreamedConnection, ITransport)
  ...
  protected
     procedure SetConnected(Value: Boolean); override;  // Add this



procedure TWebConnection.SetConnected(Value: Boolean);
var
  i : integer;
begin
  if Value = Connected then Exit;

  if not Value then
  begin
    with TDataBlockInterpreter(FInterpreter) do
      for i := FDispatchList.Count - 1 downto 0 do
      begin
        FInterpreter.CallFreeObject(TDataDispatch(FDispatchList[i]).DispatchIndex);
        FInterpreter.RemoveDispatch(TDataDispatch(FDispatchList[i]));
      end;
  end;

  inherited;
end;

---------

Added early exit

Need to modify sConnect.pas

  TWebConnection = class(TStreamedConnection, ITransport)
  ...
  protected
     procedure SetConnected(Value: Boolean); override;  // Add this



procedure TWebConnection.SetConnected(Value: Boolean);
var
  i : integer;
begin
  if Value = Connected then Exit;

  if not Value then
  begin
    with TDataBlockInterpreter(FInterpreter) do
      for i := FDispatchList.Count - 1 downto 0 do
      begin
        FInterpreter.CallFreeObject(TDataDispatch(FDispatchList[i]).DispatchIndex);
        FInterpreter.RemoveDispatch(TDataDispatch(FDispatchList[i]));
      end;
  end;

  inherited;
end;
Attachment
AppServer.zip
Comments

Richard Werning at 9/6/2002 4:14:10 PM -
If you use the demo application, be sure that you set the WebConnection.URL to your machine.

To test the fix, copy sConnect.pas to the same directory as the demo, make the changes listed in work around, then build all.

Carlos Roweder Nass at 5/5/2005 12:33:28 PM -
Hi, I tried this solution, but with no success... In code

with TDataBlockInterpreter(FInterpreter) do
  for i := FDispatchList.Count - 1 downto 0 do
  begin
    FInterpreter.CallFreeObject(TDataDispatch(FDispatchList[i]).DispatchIndex);
    FInterpreter.RemoveDispatch(TDataDispatch(FDispatchList[i]));
  end;

the debug shows me that FDispatchList.Count never has a value grater than 0, so, it never enter in FOR, and doesn't release server...

Someone have the solution? Can someone send me the sconnect.pas already modified?

Thanks



Server Response from: ETNACODE01