Gracefully shutdown EchoServer

Hi,

I have a datamodule with an TEchoServer. When I stop it and Free it, I quite often get an Access Violation that I do not understand.

My TEchoServer datamodule, was inspired by this (thanks to Mr Sinclair)

DataModule:

unit Dm.Echo.Replication;

interface

uses
  System.SysUtils, System.Classes,
  Aurelius.Drivers.Interfaces,
  Aurelius.Engine.DatabaseManager,
  XData.Server.Module,
  Sparkle.HttpSys.Server,
  Sparkle.HttpServer.Context,
  Sparkle.HttpServer.Module,
  Sparkle.Sys.Timer,
  Echo.entities,
  Echo.Listeners,
  Echo.Server,
  Echo.Main,
  Common.AureliusEntities;

type
  TdmReplication = class(TDataModule)
  private
    { Private declarations }
    FBaseUrl       : string;
    FEcho          : TEcho;
    FEchoModule    : TEchoServerModule;
    FEchoSubscriber: TEchoEventSubscriber;
    FHttpSysServer : THttpSysServer;
    FNodeManager   : IEchoNodeManager;
    FPool          : IDBConnectionPool;
    FTimer         : TSparkleTimer;

  public
    { Public declarations }
    constructor Create( ABaseUrl: string; APool: IDBConnectionPool );
    destructor Destroy; override;
    procedure Start;
    procedure Stop;

  end;

var
  dmReplication: TdmReplication;

implementation

{%CLASSGROUP 'Vcl.Controls.TControl'}

{$R *.dfm}

{ TdmReplication }

constructor TdmReplication.Create(ABaseUrl: string; APool: IDBConnectionPool);
begin
  inherited Create(nil);
  FBaseUrl       := ABaseUrl;
  FPool          := APool;
  FHttpSysServer := nil;
  FEcho          := nil;
  FTimer         := nil;
  TDatabaseManager.Update( APool.GetConnection, TEcho.Explorer );
end;

destructor TdmReplication.Destroy;
begin
  Stop;
  inherited;
end;

procedure TdmReplication.Start;
begin
  if Assigned( FHttpSysServer ) then
    Exit;

  FHttpSysServer := THttpSysServer.Create;

  FEchoModule := TEchoServerModule.Create( FBaseUrl, FPool );
  FHttpSysServer.AddModule( FEchoModule );

  FEcho := TEcho.Create( FPool );

  FNodeManager := FEcho.GetNodeManager;

  if FNodeManager.SelfNode = nil then
  begin
    FNodeManager.CreateNode( 'server' );
    FNodeManager.DefineSelfNode( 'server' );
  end;

  FEchoSubscriber := TEchoEventSubscriber.Create;
  FEchoSubscriber.SubscribeListeners;

  FTimer := TSparkleTimer.Create(
    procedure( FEcho: TObject )
    const
      ENTITY_FILE = 'Common.AureliusEntities';
    begin
      TEcho( FEcho ).BatchLoad;
      TEcho( FEcho ).Route(
          procedure( Log: TEchoLog; Node: TEchoNode; var Route: Boolean )
          begin
            // So far use only DemoTable
            if not SameText(Log.EntityClass, ENTITY_FILE + '.' + TDemoTable.ClassName) then begin
              Route := false;
            end;
          end);
    end,
    FEcho, 2000, TTimerType.Periodic );

  FHttpSysServer.Start;
end;

procedure TdmReplication.Stop;
begin
  FEchoSubscriber.UnsubscribeListeners;
  FEchoSubscriber.Free;

  FreeAndNil(FHttpSysServer);
  FreeAndNil(FEcho);
  FreeAndNil(FTimer);
end;

end.

The way I create the datamodule:

  {$IFDEF REPLICATION}
  var lPool := ApiServers.Items[ServerConfig.Urls[0]].xdPoolMain.GetPoolInterface;
  dmReplication := TdmReplication.Create('http://+:80/staweb/echo', lPool);
  dmReplication.Start;
  Logger.Log('Echo replication module started');
  {$ENDIF}

The way I destroy it is just

{$IFDEF REPLICATION}
dmReplication.Stop;
dmReplication.Free;
{$ENDIF}

May I ask if you see something obviously wrong with my code since I get this Access Violation?

Thank you in advance.

One thing that appears wrong to me is that you are destroying FEcho before destroying FTimer (which in turn uses FEcho. So one guess is that something might be related to it. I would destroy the timer first, then FHttpSyServer, then FEcho.

But indeed, this is just a guess. If this doesn't help, you could please try to provide the full call stack of the Access Violation exception so we can have a better idea of what might be happening.

1 Like

@Olsen_Leif_Eirik did this solve your issue?

Yes, I think it did. Thank you.

This topic was automatically closed 60 minutes after the last reply. New replies are no longer allowed.