Aeter
RTC Expired
![*](https://rtcforum.teppi.net/Themes/default/images/star.gif)
Posts: 36
|
![](https://rtcforum.teppi.net/Themes/default/images/post/xx.gif) |
« on: July 31, 2018, 05:37:42 PM » |
|
Hello, looking at the code I realized that by calling the function CloseSessionID the sessions are closed but the RAM is never released because the sessions are always in the SessLockList list. How I can resolve this memory leak? From rtcDataSrv.pas : function CloseSessionID(const ID,PeerAddr,ForwardedFor: RtcString; _Event:TRtcSimpleEvent):boolean; var id2:RtcString; o:TObject; sess:TRtcServerSession; begin if ID='' then Result:=false else begin SessCS.Acquire; try if assigned(SessUnLockList) then begin id2:=ID; {$IFNDEF UseGUIDs} // Set ID to desired length, so it will be sorted as a numeric value. while length(id2)<RTC_SESSIONID_LENGTH do id2:=' '+id2; {$ENDIF}
// Find Session with Session ID inside unlocked sessions list o:=SessUnLockList.search(id2); if o<>nil then begin sess:=TRtcServerSession(o); // Check if we have the right to access this session if sess.DenyAccess(PeerAddr,ForwardedFor) then Result:=False else begin // Remove from UnLocked list SessUnLockList.remove(id2); // Remove from Expiring list SessExpList.remove(SessionTimeToStr(sess.ExpireTime)+sess.ID); // Call SessionClose event. if assigned(_Event) then _Event(sess); // Free session object RtcFreeAndNil(sess); Result:=True; end; end else begin // Find Session with Session ID inside Locked Sessions list o:=SessLockList.search(id2); if o<>nil then begin sess:=TRtcServerSession(o); // Check if we have the right to access this session if sess.DenyAccess(PeerAddr,ForwardedFor) then Result:=False else begin sess.FinalExpire:=Now; Result:=True; end; end else Result:=False; end; end else Result:=False; finally SessCS.Release; end; end; end;
|
|
|
Logged
|
|
|
|
D.Tkalcec (RTC)
|
![](https://rtcforum.teppi.net/Themes/default/images/post/xx.gif) |
« Reply #1 on: July 31, 2018, 06:28:36 PM » |
|
Expired and/or Closed Sessions can ONLY be released from Memory if they are "unlocked" (NOT referenced by another RTC component).
If you close a "Locked" Session (the Session is still referenced by a RTC connection component), the Session object will be marked as "Expired", but it will NOT be released from Memory, as long as the Session remains "Locked".
If you have manually locked a Session (for example, by calling the "FindSession" or "OpenSession" method), you can unlock your Session by using the "UnLockSession" method (used on the same component where "FindSession" or "OpenSession" was used to lock the Session).
If a Session was locked automatically by a RTC component (for example, a "TRtcServerModule" with Automatic Sessions), the Session will be unlocked by that same component, once it is no longer needed to complete processing the request (response was prepared or connection closed).
|
|
|
Logged
|
|
|
|
Aeter
RTC Expired
![*](https://rtcforum.teppi.net/Themes/default/images/star.gif)
Posts: 36
|
![](https://rtcforum.teppi.net/Themes/default/images/post/xx.gif) |
« Reply #2 on: August 01, 2018, 08:39:04 AM » |
|
Sessions are automatically locked, but then they never come unlocked and therefore the memory remains available but occupied by the component for the whole life of the program.When the client disconnects the server (TRtcBaseServerModule) it must release all the resources occupied by it.
|
|
|
Logged
|
|
|
|
D.Tkalcec (RTC)
|
![](https://rtcforum.teppi.net/Themes/default/images/post/xx.gif) |
« Reply #3 on: August 01, 2018, 08:42:23 AM » |
|
Where did you get that idea from? If that were the case, then it would be a bug.
Can you post a short example Project reproducing this behavior?
|
|
|
Logged
|
|
|
|
Aeter
RTC Expired
![*](https://rtcforum.teppi.net/Themes/default/images/star.gif)
Posts: 36
|
![](https://rtcforum.teppi.net/Themes/default/images/post/xx.gif) |
« Reply #4 on: August 01, 2018, 09:12:38 AM » |
|
I have set autosessions to true and then the sessions manage them automatically. The problem is that when I call TRtcConnection.CloseSession (id) to close the session, It set sess.FinalExpire:=Now but then the session is never release.When I put the program in debug and I see that It never run this instruction that would free the memory: Code from rtcDataSrv.pas ( line 2008-2028) o:=SessUnLockList.search(id2); if o<>nil then begin sess:=TRtcServerSession(o); // Check if we have the right to access this session if sess.DenyAccess(PeerAddr,ForwardedFor) then Result:=False else begin // Remove from UnLocked list SessUnLockList.remove(id2); // Remove from Expiring list SessExpList.remove(SessionTimeToStr(sess.ExpireTime)+sess.ID); // Call SessionClose event. if assigned(_Event) then _Event(sess); // Free session object RtcFreeAndNil(sess); Result:=True; end; end else
This happens because the session is set as expired but then it is no longer unlocked and released!
|
|
|
Logged
|
|
|
|
D.Tkalcec (RTC)
|
![](https://rtcforum.teppi.net/Themes/default/images/post/xx.gif) |
« Reply #5 on: August 01, 2018, 09:21:13 AM » |
|
Can you post an actual example where Sessions are created and locked, but never get unlocked or released from Memory? You keep posting a function which is NOT responsible for Session memory management, but only marks Sessions as expired. The method responsible for clearing up the Memory from expired sessions is "UnLockSession" and ... that method is called automatically in several places (search for "InitSesssion" method in the same unit, which calls "UnLockSession" if a Session is locked). { UnLock Session and remove all sessions that have expired: - remove from Locked list - add to UnLocked and Expiring list } procedure TRtcServerSession.UnLockSession(_Event:TRtcSimpleEvent); var id2,ex:RtcString; o:TObject; begin if not assigned(SessCS) then Exit;
SessCS.Acquire; try if assigned(SessUnLockList) then begin // Check if there are Sessions that have expired but are still in our session list ex:=SessExpList.search_min(o); while (ex<>'') and (TRtcServerSession(o).ExpireTime<=Now) do begin // Remove from Expiring list SessExpList.remove(ex);
// Set ID to desired length, so it will be sorted as a numeric value. id2:=TRtcServerSession(o).ID; {$IFNDEF UseGUIDs} while length(id2)<RTC_SESSIONID_LENGTH do id2:=' '+id2; {$ENDIF}
// Remove from UnLocked list SessUnLockList.remove(id2);
if assigned(_Event) then _Event(o); // Free the Session object RtcFreeAndNil(o);
ex:=SessExpList.search_min(o); end;
id2:=FID; {$IFNDEF UseGUIDs} // Set ID to desired length, so it will be sorted as a numeric value. while length(id2)<RTC_SESSIONID_LENGTH do id2:=' '+id2; {$ENDIF}
// Remove from Locked list SessLockList.remove(id2);
// Free if expired, add to expiring list if not. if ExpireTime<=Now then begin if assigned(_Event) then _Event(self); {$IFDEF NEXTGEN} DisposeOf; {$ELSE} Free; {$ENDIF} end else begin // Add to UnLocked list SessUnLockList.insert(id2, self); // Add to Expiring list SessExpList.insert(SessionTimeToStr(ExpireTime)+ID, self); end; end; finally SessCS.Release; end; end;
|
|
|
Logged
|
|
|
|
Aeter
RTC Expired
![*](https://rtcforum.teppi.net/Themes/default/images/star.gif)
Posts: 36
|
![](https://rtcforum.teppi.net/Themes/default/images/post/xx.gif) |
« Reply #6 on: August 01, 2018, 09:35:24 AM » |
|
The code is quite complex, however when a client disconnect from server this function is performed: procedure TGateway.LogOutEx(Sender: TRtcConnection; Param: TRtcFunctionInfo; Result: TRtcValue); var sClientType : string; sid,a:string; closed:boolean; i:integer; begin sid:= Sender.Session.ID; Sender.Session.asBoolean['login']:=False; Sender.Session.Session.Clear; closed:=Sender.CloseSession(sid); Sender.Session.Close; if closed and writelog then xLog('Session '+sid+' closed '+' Total session remains :'+intToStr(Sender.TotalSessionsCount)); end;
I can assure you that the UnLockSession function never (NEVER) runs despite the session being closed!!
|
|
|
Logged
|
|
|
|
Aeter
RTC Expired
![*](https://rtcforum.teppi.net/Themes/default/images/star.gif)
Posts: 36
|
![](https://rtcforum.teppi.net/Themes/default/images/post/xx.gif) |
« Reply #7 on: August 01, 2018, 09:40:02 AM » |
|
I did some tests, if you connect 100 clients, 60 MB of memory is occupied, but when they are disconnected, the memory remains busy. If you reconnect them all and 100 no more memory is added, but if you connect 200 120MB of memory are occupied .. and so on
I think this happens because the program knows that that portion of memory occupied by expired sessions is free, but does not release it!
|
|
|
Logged
|
|
|
|
D.Tkalcec (RTC)
|
![](https://rtcforum.teppi.net/Themes/default/images/post/xx.gif) |
« Reply #8 on: August 01, 2018, 09:54:19 AM » |
|
You can check how many Sessions are still in Memory with "TotalSessionsCount", "TotalSessionsLocked" and "TotalSessionsUnlocked" methods, which are all available on the "Sender:TRtcConnection" component (passed to all RTC components events).
If you want to debug Session management, make sure you are using more than one Session, because the expiration time of a Session is automatically extended each time you try to access that Session. This is by design, to avoid Sessions being released from Memory just before they are needed (since that would be counter-productive). In other words, expired and closed Sessions would ONLY be released from Memory when another Session is unlocked, which can NOT happen if you only use a single Session.
Also, do NOT use the Windows Task Manager to check how much RAM your Application is using, because Delphi Applications use a Memory Manager which allocates RAM from the OS in large blocks, then manages memory allocations inside these blocks for you. If you are unfamiliar with Memory Management in Delphi, try googling "Delphi Memory Management" or "delphi fastmm".
|
|
|
Logged
|
|
|
|
Aeter
RTC Expired
![*](https://rtcforum.teppi.net/Themes/default/images/star.gif)
Posts: 36
|
![](https://rtcforum.teppi.net/Themes/default/images/post/xx.gif) |
« Reply #9 on: August 01, 2018, 10:49:44 AM » |
|
I use ProcessHacker to monitor the RAM and I've done both test with the program in debugging and in running mode. The problem is that on 100 open and then closed sessions none is permanently destroyed by executing the RtcFreeAndNil (o) statement (line 3905 of rtcDataSrv.pas). In fact, the component then, when other connections arrive reuses that busy ram, but I would like when there is a disconnection the ram used for that session is deallocated.
|
|
|
Logged
|
|
|
|
D.Tkalcec (RTC)
|
![](https://rtcforum.teppi.net/Themes/default/images/post/xx.gif) |
« Reply #10 on: August 01, 2018, 10:59:38 AM » |
|
I think you really should read about Memory Management in Delphi before you continue making assumptions. Also, if you are looking for a place to put a break-point, so you can see when RTC Session objects are being released from Memory and destroyed, open the "rtcInfo.pas" unit and find the "TRtcSession.Destroy" method there, then place a break-point at the line where FID and FPeerAddr variables are cleared. This should be line 31972 if you are using the latest RTC SDK version ... destructor TRtcSession.Destroy; begin try // {$IFDEF RTC_EXTDEBUG}Log('TRtcSession.Destroy "'+FID+'" ('+FPeerAddr+')','DEBUG');{$ENDIF} FID:=''; FPeerAddr:=''; // <- place a breakpoint on THIS line! inherited; // {$IFDEF RTC_EXTDEBUG}Log('TRtcSession.Destroyed.','DEBUG');{$ENDIF} except on E:Exception do begin if LOG_AV_ERRORS then Log('TRtcSession.Destroy',E,'ERROR'); raise; end; end; end;
|
|
|
Logged
|
|
|
|
Aeter
RTC Expired
![*](https://rtcforum.teppi.net/Themes/default/images/star.gif)
Posts: 36
|
![](https://rtcforum.teppi.net/Themes/default/images/post/xx.gif) |
« Reply #11 on: August 01, 2018, 11:38:34 AM » |
|
I put the break point there (line 31971 of RTCInfo.pas) and in fact the component destroys the Session object, but the fact remains that the memory remains busy !!
|
|
|
Logged
|
|
|
|
D.Tkalcec (RTC)
|
![](https://rtcforum.teppi.net/Themes/default/images/post/xx.gif) |
« Reply #12 on: August 01, 2018, 12:05:19 PM » |
|
Delphi Memory Management. Read about it. Seriously.
|
|
|
Logged
|
|
|
|
Aeter
RTC Expired
![*](https://rtcforum.teppi.net/Themes/default/images/star.gif)
Posts: 36
|
![](https://rtcforum.teppi.net/Themes/default/images/post/xx.gif) |
« Reply #13 on: August 01, 2018, 01:08:34 PM » |
|
Could you try to see if there is a memory leak with connections (many connections) on TRtcBaseServerModule?
|
|
|
Logged
|
|
|
|
D.Tkalcec (RTC)
|
![](https://rtcforum.teppi.net/Themes/default/images/post/xx.gif) |
« Reply #14 on: August 01, 2018, 01:35:40 PM » |
|
Done. No Memory Leaks found.
|
|
|
Logged
|
|
|
|
|