![]() |
Eigener Dienst -> Speicherauslastung wächst und wächst...
Liste der Anhänge anzeigen (Anzahl: 1)
Hi
bin grad drann mein erster eigener Dienst zu proggen. Eigentlich funktioniert alles so wie es soll. Nur eines nicht. Die Speicherauslastung des Services vergrössert sich um ca. 4 KByte pro sekunde... Proportional zu E/A andere, beides im Taskmgr gesehen... Irgendwo hab ich wohl vergessen speicher freizugeben oder so... aber wo??? so sieht mein ServiceExecute aus:
Delphi-Quellcode:
Der ganze Quellcode im Anhang...
procedure TSisterWatch.ServiceExecute(Sender: TService);
begin //ShowMessage('OnExecute - begin'); while not Terminated do begin TRY // try to catch a user if Username <> '' then begin // AUTOSCAN // THIS SECTION IS FOR USER WHO JUST LOGGED IN if (Username <> GetSession) or (Welcome = False) then begin Username := GetSession; // If the logged in user is not on the blacklist it will autoscan now if not IgnoreUser then begin Welcome := True; Log('logged in with IPAddress: '+GetIPAddress); // get about the users logontime logontime := Now; // check if the user already exists in the database CheckDBforUser(ADOQuery1,ADOStoredProc1); // Save to database that the user is logged in UpdateUserInfo(Username, 1); // get all info from User Table "t_bb_user" ADOQuery3.Close; ADOQuery3.Parameters.ParamValues['@username'] := username; ADOQuery3.Open; if ADOQuery3autostart.AsBoolean then ScanAndWriteToDB; // Activate TCP Server ActivateTCPServer; end; end else if StartManScan then begin try // check if the user already exists in the database CheckDBforUser(ADOQuery1,ADOStoredProc1); ScanAndWriteToDB; finally // its very important to reset the variable StartManScan StartManScan := False; end; end; end else Username := GetSession; EXCEPT on e:Exception do LOG('FATAL ERROR#@: '+e.Message); END; ServiceThread.ProcessRequests(False); Sleep(1000); end; //ShowMessage('OnExecute - end'); end; |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
Da wird vermutlich bei jedem Durchlauf ein Objekt angelegt aber nie wieder freigegeben.
Also wird jedes mal ein neues Objekt erzeugt. Somit wächst der Speicherbedarf kontinuierlich. |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
Was macht GetSession?
|
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
Zitat:
Zitat:
Delphi-Quellcode:
// Ergänzung:
function TSisterWatch.GetSession: String;
//var // TS : TJwTerminalServer; --> wurde testhalber als public var von TSisterWatch deklariert begin try TS := TJwTerminalServer.Create; TS.Connect; TS.EnumerateSessions; Result := TS.Sessions[0].Username; // every second before the first login it raise an exception! FreeAndNil(TS); {its very important to free TS memory!} except FreeAndNil(TS); {its very important to free TS memory!} end; end; Eigentlich hab ich zuerst gedacht, dass es an eben dieser Funktion liegen muss, da dies die einzige ist, die immer wieder aufgerufen wird... aber TS wird ja immer wieder freigegeben oder nicht? |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
anstelle von except kannst du mit finally arbeiten dann sparst du dir die doppelte ausführung von freeandnil
|
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
Warum arbeitest Du zum Merken der Dateiinformationen mit 7 Stringlisten anstelle von Array of TSearchRec ? Der Speicherverbrauch kann auch daran liegen, dass die Datensätze gecached werden. Im Zweifelsfall verwendest Du FastMM oder ähnliche um zu ermitteln, wo das evtl. leckt.
|
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
Zitat:
Zitat:
kann noch mal jmd einen Blick drauf werfen? Gesammte Sourcecode steht als "main.pas" im ersten Beitrag zum DOWNLOAD bereit. |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
Hallo,
warum nimmst du nicht MemCheck oder FastMM4 und überlässt denen die Suche nach dem Leck ? Heiko |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
Du verwendest dort die TIndyBaseClientData. Ist da vielleicht der Fehler, denn das wird bei jedem Connect created?
[edit]Und lesen hilft Zitat:
![]() [/edit] |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
Zitat:
Zitat:
Hab mal irgendwo gelesen, dass wenn ich mein Programm (in meinem fall ein Dienst) beende, sollte ich eine MsgBox von FastMM sehen, auch diese sehe ich NICHT... :gruebel: |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
Hallo,
also ich benutze ja memcheck. In der dpr als 1 .unit uses MemCheck und nach begin MemChk; Ich würde den Code mal in ein normales Programm kopieren und dort laufen lassen. Memcheck zeigt nach dem Abschluss eine Datei mit memleaks an. Heiko |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
Ok, dann versuch ichs mal mit MemCheck... wo krieg ich denn das her?
|
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
|
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
Hallo,
und dann in der dpr als erste unit MemCheckrein und in der dpr als 1. Zeile MemChk; dann ein komplettes Rebuild und Programm laufen lassen. Nach dem Beenden zeigt er die memleaks an. Heiko |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
TJwTerminalServer.Enumeratesessions erzeugt ein Memoryleak, weil es einen Thread verwendet, der eine Variable nicht freigibt. In der Subversion Trunk version ist dieser Fehler behoben.
You should update your source to the latest version in the version control repository and try again. To do so, use a subversion client like Tortoise SVN and just hit SVN update in the explorer's context menu on the "trunk" folders of JWSCL also JWA. Der GetSessionCode ist übrigens inkorrekt. So stimmt es schon eher
Delphi-Quellcode:
function TSisterWatch.GetSession: String;
var TS : TJwTerminalServer; begin TS := TJwTerminalServer.Create; try TS.Connect; TS.EnumerateSessions; Result := TS.Sessions[0].Username; // every second before the first login it raise an exception! except result := ''; end; FreeAndNil(TS); {its very important to free TS memory!} end; |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
Du kannst auch schneller an den Benutzernamen der Session 0 herankommen.
Siehe ![]() |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
Hi Dezipaitor
Zitat:
Zitat:
also meinst du nicht auch, dass dies die neuste Version ist: ![]() die hab ich jetzt runtergebeamt kompilliert und verwendet. Das Phänomen ist aber immer noch vorhanden?! hab ich jetzt was verpasst?! -Haste wohl nicht ganz so gemeint oder?:gruebel: :oops: //EDIT -> hehe, hab wohl das englische nicht ganz kapiert zu beginn... versuche das jetzt mal, melde dann mein Status zurück... |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
Version 316 ist die neueste Release version. Es gibt neuere Version im Entwicklerzweig (trunk).
|
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
hab jetzt also SVN Update (TortoiseSVN) auf folgende Ordner gemacht.
...\JWSCL\jedi-api-lib\jwapi\trunk ...\JWSCL\jedi-api-lib\jwscl\trunk und alle 4 Projekte in "JWSCL\jedi-api-lib\jwapi\trunk\Packages\bds10\JediApi_Bds10.bdsgr oup" neu kompilliert sollte mein Speicherproblem jetzt nicht vom Tisch sein? -Ist aber immer noch dasselbe... hab ich was übersehen beim updaten von trunk?!... |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
mach getSession raus und nutze stattdessen deinen Benutzername. Wenn es immernoch ein Speicherleck gibt, dann ist es was anderes.
|
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
Zitat:
hab ich was mit trunk update verpasst... ? |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
I tested the code and my results on Vista SP1/D2007 are as follows:
Neither Eurekalog nor FastMM detects a memory leak, yet taskmanager shows an increase in memory usage. So there seems to be a memory leak but I am not sure if we are leaking the code in Jwscl or somewhere in an API call. Could you please indicate your OS version? |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
Mein Betriebssystem ist:
Windows XP Professional Version 2002 SP2 ... Ich denke aber ich hab was beim Update der Subversion von JEDI falsch gemacht... respektive beim kompillieren... ich hab danach nur "JWSCL\jedi-api-lib\jwapi\trunk\Packages\bds10\JediApi_Bds10.bdsgr oup" geöffnet und die dort enthaltenen Units neu kompilliert. Nicht aber z.B. die pas Dateien unter: ...\JWSCL\jedi-api-lib\jwscl\trunk\source muss ich die auch noch? oder muss ich sonst noch was neu kompillieren? oder reicht "JediApi_Bds10.bdsgroup" aus? |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
XP 2002 SP2 ? hab ich was verpasst?
schau mal in die Unit JwsclUtils.pas und suche nach der Variablen: InternalThreadName . Welchen Typ hat die? JWSCL wird nicht, wie die JWA einzeln kompiliert. Man kompiliert die JWA in dcu Dateien nur damit ein Rebuild des Projektes nicht so ewig dauert. |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
WideString!
Delphi-Quellcode:
wieso? haste noch ne Idee?
threadvar InternalThreadName : WideString;
|
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
Also bei mir erkennt kein Memorymanager ein Leak. Wenn ich Private Memory Data von einem Testprogramm anschaue, dann sieht man aber einen Anstieg des Speicherverbrauchs. Da kein Memorymanager in Delphi, dieses erkennt, ist meine Schlussfolgerung, dass der Speicher nicht durch die Delphianwendung direkt erzeugt wird (kein Objekt, kein GetMem usw). Da er ja sonst angezeigt werden würde.
Das Problem sind die WTSxxx Funktionen, welche Private Memory resevieren. Obwohl WTSFreeMemory dafür aufgerufen wird, konnte ich nicht sehen, dass Private Memory weniger wurde. Entweder ist das ein Bug von MS, oder ich blicke nicht ganz durch. Intern ruft WTSFreeMemory auch nur LocalFree auf. |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
schade, ich denke wir werden nie rauskriegen wo das Problem liegt...
ich versuch das Problem jetz halt so zu umgehen: Zitat:
Delphi-Quellcode:
funktioniert aber leider nicht. Ich hab auch schon probiert mit GetCurrUserName statt mit GetEnvironmentVariable('USERNAME') dort erhalte ich zwar sogar als Dienst den richtigen Username, allerdings ist der String irgendwie korrupt oder viel zu lang oder schneidet mir was ab oder weissnichtwas...
function TSisterWatch.GetSession: string;
begin try Token := TJwSecurityToken.CreateCompatibilityQueryUserToken(MAXIMUM_ALLOWED, 'explorer.exe'); Token.ImpersonateLoggedOnUser; //do stuff on user’s behalf Result := GetEnvironmentVariable('USERNAME'); except Result := ''; end; Token.RevertToSelf; Token.Free; end; hier noch meine GetCurrUserName funktion... (Vielleicht ist ja nur die falsch...)
Delphi-Quellcode:
z.b. showmessage('"'+GetSession'"') würde folgendes erzielen: Ausgabe["Username] das an den String angefügte, hier ein ", greifft nicht!
function GetCurrUserName: string;
var Size : DWORD; begin Size := MAX_COMPUTERNAME_LENGTH + 1; SetLength(Result, Size); if GetUserName(PChar(Result), Size) then SetLength(Result, Size) else Result := ''; end; JMD eine Idee? so kann ich den Benutzername aber auch nicht gebrauchen... // EDIT: Kann ich nicht einfach den Username irgendwie aus dem Token bekommen? ... |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
CreateCompatibilityQueryUserToken sollte man wirklich nur im Ausnahmefall verwenden.
Delphi-Quellcode:
ist die beste Variante.
Token := TJwSecurityToken.CreateWTSQueryUserTokenEx(WTS_CURRENT_SERVER_HANDLE, WtsGetActiveConsoleSessionID);
Wenn du schon die Trunkversion hast, dann gibt es dazu die Methode : GetTokenUserName |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
hmm...
meinst du nicht eher:
Delphi-Quellcode:
aber anyway, wo kriege ich die SessionID her?!
CreateWTSQueryUserToken(SessionID: cardinal = INVALID_HANDLE_VALUE); overload; virtual;
|
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
die Ex Version funktioniert auch unter Windows 2000.
WtsGetActiveConsoleSessionID gibt die die SessionID vom physisch eingeloggten Benutzer. |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
habs jetzt mal so...
Delphi-Quellcode:
:dancer2: --> Ohne wachsende Speicherauslastung
function TSisterWatch.GetSession: string;
begin try Token := TJwSecurityToken.CreateWTSQueryUserToken(WtsGetActiveConsoleSessionID); // Token := TJwSecurityToken.CreateCompatibilityQueryUserToken(MAXIMUM_ALLOWED, 'explorer.exe'); Token.ImpersonateLoggedOnUser; //do stuff on user’s behalf Result := Token.GetTokenUserName; except Result := ''; end; Token.RevertToSelf; Token.Free; end; scheint aber "nur" als dienst (systemkonto) zu funktionieren!!! -> Habs zuerst als normales Programm getestet... ist das normal? muss jetzt leider gleich weg... versuche morgen noch mit der Ex Version.... bei der Ex Version muss man noch nen Terminalserver angeben als Parameter, geht das also auch Remote? nehm ich an... |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
1. ha das benötigt einen Dienst!
2. ImpersonateLoggedonuser ist hier nicht mehr nötig! |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
Hallo,
Delphi-Quellcode:
das sieht nicht gut aus !
function GetCurrUserName: string;
var Size : DWORD; begin Size := MAX_COMPUTERNAME_LENGTH + 1; SetLength(Result, Size); if GetUserName(PChar(Result), Size) then SetLength(Result, Size) else Result := ''; end;
Delphi-Quellcode:
function GetCurrUserName: string;
var Size : DWORD; sUserName : String; begin Result:= ''; Size := MAX_COMPUTERNAME_LENGTH + 1; SetLength(sUserName, Size); if GetUserName(PChar(sUserName), Size) then Result:= sUserName; end; Heiko |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
also ich krieg das mit Ex nicht hin... Ich weiss nicht welche Parameter?!
![]()
Delphi-Quellcode:
Token := TJwSecurityToken.CreateWTSQueryUserTokenEx(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION);
Delphi-Quellcode:
geht aber beides nicht... ich denke es liegt am ersten Parameter Server:TObject
Token := TJwSecurityToken.CreateWTSQueryUserTokenEx(WTS_CURRENT_SERVER_HANDLE, WtsGetActiveConsoleSessionID);
Zitat:
[Pascal Fehler] main.pas(371): E2250 Es gibt keine überladene Version von 'CreateWTSQueryUserTokenEx', die man mit diesen Argumenten aufrufen kann |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
Uh ja das ist mein Fehler. Im parallelen branch hab ich die Doku dazu schon angepasst. Nimm als erster parameter nil. Normal kommt da sonst TJwTerminalServer Objekt rein. Ich hab auch den Blog angepasst.
|
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
The leak seems to be in WTSAPI32.DLL and specifically in the function WTSQuerySessionInformation with information classes WTSInitialProgram and WTSApplicationName.
You can test by looking up this part of JwsclTerminalServer:
Delphi-Quellcode:
and comment out these lines:
constructor TJwWTSSession.Create(const Owner: TJwWTSSessionList;
const SessionId: TJwSessionId; const WinStationName: TJwString; const ConnectState: TWtsConnectStateClass);
Delphi-Quellcode:
Windows Vista and XP seem to suffer, 2003 server seems to be ok.
FApplicationName := GetSessionInfoStr(WTSApplicationName);
FInitialProgram := GetSessionInfoStr(WTSInitialProgram); |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
ich habs jetzt mal so gemacht...
Delphi-Quellcode:
1'000'000'000 Dank euch allen! Scheint prima zu funktionieren.
function TSisterWatch.GetSession: string;
begin try Token := TJwSecurityToken.CreateWTSQueryUserTokenEx(nil{or a TJwTerminalServer object}, WtsGetActiveConsoleSessionID); // Token.ImpersonateLoggedOnUser; <- Its not necessary //do stuff on user’s behalf Result := Token.GetTokenUserName; except Result := ''; end; Token.RevertToSelf; Token.Free; end; |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
hehe... hab grad folgendes festgestellt...
(Ich überprüfe ja jede Sekunde einmal, ob der Benutzer gewechselt hat. mir der Funktion GeSession von oben...) Wenn ich jetzt den Dienst auf einem Rechner laufen habe funktioniert das super. Melde ich mich jetzt aber remote an diesem Rechner an (RDP), wirft die die Funktion GetSession folgende Fehlermeldung : Zitat:
wie würdet ihr das behandeln? -> ich meine ich will ja herausfinden wann sich ein anderer Benutzer angemeldet hat und solange ich eine RDP session habe, ists je eh immer der gleiche Benutzer. Also nicht weiter tragisch, oder wie seht ihr das? |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
Only the system account is allowed to retreive the token (since it is the user's primary access token). So my question is are you retreiving the token as system or as user/administrator?
PS: see my post above, maybe you can revert to the original code? |
Re: Eigener Dienst -> Speicherauslastung wächst und wächs
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:50 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz