Olympia - Events - Memory leak

Having an Olympia server and several other services (executables) which are ‘monitored’ by the Olympia service.

One of the services is a ‘broadcast’ service to broadcast events to all users despite the application they use nor the service to which they connect.
So, the client requests something from the productionservice, the productionservice requests a broadcast from the broadcastservice and the broadcastservice ‘broadcasts’ an event. (extract of the code below)

When I stop the broadcast-executable, an ROSession is leaked… I can’t solve it…:unamused:

Broadcastservice has requiresession false, the productionservice has requiresession true.

Regards,
Filip

procedure TBroadCastService.SendToAll(const Message: TBroadCast);
var
  sList: TStringList;
  saService: ServiceApplication; //enum of applications in use
begin
  sList := TStringList.Create;

  try
    for saService := Low(ServiceApplication) to High(ServiceApplication) do
      if saService <> saUnknown then
      begin
        TROOlympiaSessionManager(SessionManager).ApplicationID := saService.ID;
        SessionManager.GetAllSessions(sList);
      end;

    Send(Message, sList);
  finally
    sList.Free;
  end;
end;

procedure TBroadCastService.Send(const aBroadCast: TBroadCast;
  const Sessions: TStrings);
var
  anEvent: IBroadCastEvent_Writer;
begin
  anEvent := (EventRepository as IBroadCastEvent_Writer);
  anEvent.SessionList.Clear;

  anEvent.SessionList.AddStrings(Sessions);
  anEvent.ExcludeSessionList := False;
  anEvent.ExcludeSender := True;

  // register all clients
  for iCnt := 0 to anEvent.SessionList.Count - 1 do
    RegisterEventClient(AnsiString(anEvent.SessionList.Strings[iCnt]), EID_BroadCastEvent);

  anEvent.OnBroadCast(ClientID, aBroadCast);
end;

from this piece of code I can’t detect the problem with leaking TROSession.

Can you create a simple testcase that reproduces this problem, pls?
you can attach it here or send directly to support@

Hi Evgeny,

It’s not easy to isolate the necessary code…
Would this be helpful? If not I’ll try to create a testcase…

As you can see the SendToAll method is called, then the Send (as shown in the code above).
It looks like after the session had been created, it’s never freed, not even when I call DestroySession when I close the application.

Regards,

Filip.

from your screenshot, it seems that after changing ApplicationID, SessionManager can’t find session and created a new one.
as a result, existing instance of ROSession could be overridden with newly created so memory leak may appear

also check this case: the session should be deleted with the same ApplicationID that was used at creating session.

Indeed, that’s the issue. The sessionmanager can’t find the (newly) created session, because it is never ‘registered’ with the Olympia server.
The OnSessionCreated event is fired, but the session ID never appears in de database (Olympia with SQL Server).
Even if I do a GetAllSessions, the session ID is not in the list.

Could it be that RequireSession := False is the cause that the SessionID is not registered in de DB (and eventually causes the memory leak)?

I attached a full logging from starting the service - executing a SendToAll - and shutting down. As you can see, the session is created but can’t be found.

> 04-02-2016 14:12:37 - DEBUG MODE
> 04-02-2016 14:12:37 - 04-02-2016 14:12:37 - Database Alias:  (TEST)
> 04-02-2016 14:12:37 - 04-02-2016 14:12:37 - Listening on port: (7215)
> 04-02-2016 14:12:39 - Enter method: Server activate
> 04-02-2016 14:12:39 - Exit method: Server activate
> 04-02-2016 14:12:40 - Enter method: Session created
> 04-02-2016 14:12:41 - {5E0667D3-4BC5-40D9-8337-8DE2209D0990}
> 04-02-2016 14:12:41 - Exit method: Session created
> 04-02-2016 14:12:41 - Enter method: BroadCastService - SendToAll
> 04-02-2016 14:12:41 - Log event 1
> 04-02-2016 14:12:41 - --> Session ({5E0667D3-4BC5-40D9-8337-8DE2209D0990})
> 04-02-2016 14:12:41 - --> Application ({4168BCC7-663B-4E3A-8EAF-6ED96FE40338})
> 04-02-2016 14:12:41 - Log event 2
> 04-02-2016 14:12:41 - --> Session ({5E0667D3-4BC5-40D9-8337-8DE2209D0990})
> 04-02-2016 14:12:41 - --> Application ({4168BCC7-663B-4E3A-8EAF-6ED96FE40338})
> 04-02-2016 14:12:41 - Log event 3
> 04-02-2016 14:12:41 - --> Session ({5E0667D3-4BC5-40D9-8337-8DE2209D0990})
> 04-02-2016 14:12:41 - --> Application ({4168BCC7-663B-4E3A-8EAF-6ED96FE40338})
> 04-02-2016 14:12:41 - Log event 4
> 04-02-2016 14:12:41 - --> Session ({5E0667D3-4BC5-40D9-8337-8DE2209D0990})
> 04-02-2016 14:12:41 - --> Application ({4168BCC7-663B-4E3A-8EAF-6ED96FE40338})
> 04-02-2016 14:12:41 - Added session to broadcastlist ({E383440F-D667-4B60-BCAE-F0341E917A76})
> 04-02-2016 14:12:41 - Log event 5
> 04-02-2016 14:12:41 - --> Session ({5E0667D3-4BC5-40D9-8337-8DE2209D0990})
> 04-02-2016 14:12:41 - --> Application ({4168BCC7-663B-4E3A-8EAF-6ED96FE40338})
> 04-02-2016 14:12:41 - Log event 6
> 04-02-2016 14:12:41 - --> Session ({5E0667D3-4BC5-40D9-8337-8DE2209D0990})
> 04-02-2016 14:12:41 - --> Application ({4168BCC7-663B-4E3A-8EAF-6ED96FE40338})
> 04-02-2016 14:12:41 - Log event 7
> 04-02-2016 14:12:41 - --> Session ({5E0667D3-4BC5-40D9-8337-8DE2209D0990})
> 04-02-2016 14:12:41 - --> Application ({4168BCC7-663B-4E3A-8EAF-6ED96FE40338})
> 04-02-2016 14:12:41 - Log event 8
> 04-02-2016 14:12:41 - --> Session ({5E0667D3-4BC5-40D9-8337-8DE2209D0990})
> 04-02-2016 14:12:41 - --> Application ({4168BCC7-663B-4E3A-8EAF-6ED96FE40338})
> 04-02-2016 14:12:49 - Trying to find session ({5E0667D3-4BC5-40D9-8337-8DE2209D0990}) - did NOT succeed
> 04-02-2016 14:12:49 - Event broadcasted
> 04-02-2016 14:12:49 - Exit method: BroadCastService - SendToAll

not yet. because any login service has RequireSession := False

btw, do you call CreateSession or addess to Session in your “login” method?

I created a the session in the OnActivate of the BroadCastService (to test - as shown in the log).

There is no login involved in that particular situation. A client logs in due to a call to the production service (OnLoginNeeded). Due to that call the production service ‘needs’ to broadcast an event. So, the production service becomes a client of the broadcast service, but never logs in.

>     Client application --> Production service --> Login service --> Olympia service
>                                   |                                          |
>                                   |                                          |
>                                   |<---> BroadCast service <---------------->|

You need to release session otherwise SessionManager doesn’t see it:

      lSession := SessionManager.CreateSession(ClientID);
      SessionManager.ReleaseSession(lSession, true);

in this way, better to don’t touch Session property or CreateSession method because it will create a duplicate session.

Hi Evgeny,

First of all, I would like to thank you for your help.
Unfortunately, the problem persists…

I narrowed it down to this:

It seems that the RegisterEventClient creates a session although the session exists?

procedure TBroadCastService.Send(const aBroadCast: TBroadCast;
  const Sessions: TStrings);
var
  anEvent: IBroadCastEvent_Writer;
  iCnt: Integer;
  lSession: TROSession;
begin
  anEvent := (EventRepository as IBroadCastEvent_Writer);
  anEvent.SessionList.Clear;

  anEvent.SessionList.AddStrings(Sessions);
  anEvent.ExcludeSessionList := False;
  anEvent.ExcludeSender := True;

  // register all clients for the event
  for iCnt := 0 to anEvent.SessionList.Count - 1 do
  begin
    lSession := SessionManager.FindSession(StringToGuid(anEvent.SessionList.Strings[iCnt]));
    if Assigned(lSession) then
    begin
      Log.Add('Found session', anEvent.SessionList.Strings[iCnt]);

      RegisterEventClient(lSession, EID_BroadCastEvent); // ** --> leak occurs here **
      SessionManager.ReleaseSession(lSession, True);
    end;
  end;

  anEvent.OnBroadCast(ClientID, aBroadCast);

  Log.Add('Event broadcasted');
end;

can you create a simple testcase that reproduces this leak, pls?
you can attach it here or send to support@