Implement a session keep alive in TROInMemorySessionManager

Hello,

I have a situation here where (bogus) clients use multiple channels to start/end sessions in parallel which leads to the following situation:

Thread1: CreateSession
Thread2: CreateSession
Thread2: EndSession
Thread1: Access Session.Value
Thread1: EndSession

Because both threads are for the same client, they send the same GUID and thus access the same session object.
In the above case, it’s quite possible that the session object has been destroyed, leading to an access violation in the server.
I already have a fix for the clients but because the update cycle for those is quite slow, I’m looking for a solution inside the server itself over which I have much more control.
In my case, as I’m using TROInMemorySessionManager, I have decided to implement a “KeepAlive” mechanism inside it, so that when a session is asked to be destroyed, I actually expire it “in the past” and leave it sitting there to be destroyed by the expiration check timer when it does its job.

This avoids the race condition above with a relatively low impact on memory, provided the expiration timer runs on a smaller interval than the default 15 minutes.

Note that this suggestion was the reason for discovering the leak in TROInMemorySessionManager.DoGetAllSessions as reported here

Here is a patch for this change, should you choose to implement it:

uROSessions.pas.zip (861 Bytes)

By default, the KeepAlive mechanism is disabled to leave the current behavior untouched.

Hi,

I think, you can create a descendant of TROInMemorySessionManager with this functionality and use it inside your application.

It’s quite inconvenient to do so as right now, everything is placed on a datamodule and configured via the DFM properties.

Hi,

as for me, it isn’t a big problem to

  • create a new package
  • put unit with TMyInMemorySessionManager class to it
  • install package
  • do replacement inside project folder with notepad++:
    • TROInMemorySessionManager with TMyInMemorySessionManager in *.pas & *.dfm
    • uROSessions with uROSessions, uMyInMemorySessionManager in *.pas

if TROInMemorySessionManager was created in code, steps are more simplified