AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Speicherfresser CreateProcess?

Ein Thema von Angel4585 · begonnen am 3. Nov 2009 · letzter Beitrag vom 4. Nov 2009
Antwort Antwort
Angel4585

Registriert seit: 4. Okt 2005
Ort: i.d.N.v. Freiburg im Breisgau
2.199 Beiträge
 
Delphi 2010 Professional
 
#1

Speicherfresser CreateProcess?

  Alt 3. Nov 2009, 10:17
Guten Morgen!

Ich überarbeite gerade einen Dienst der in bestimmten Intervallen einen Prozess unter einem Benutzerkonto startet.

Nun hab ich in meiner CreateProcess Methode ein Speicherleck, hab aber keine so rechte Ahnung wie genau ich damit umgehen muss. Hier mal der Code der Methode:

Delphi-Quellcode:
procedure TMyDienst.CreateNewUserProcess(AUser, APassword, ADomain, AProgram : string);
var
  ltoken : Cardinal;
  LEnv : Pointer;
  pi : TProfileInfo;
  si : STARTUPINFO;
  pri : _PROCESS_INFORMATION;
  sil : TSecurityImpersonationLevel;
  LUser, LDomain, LPassword, LProgram : string;
  reg : TRegistry;
begin

try

  LUser:=AUser;
  LPassword:=APassword;
  LDomain:=ADomain;
  LProgram:=AProgram;
    snlogger.Log(Format('mem a: %d',[SNGetWorkingSetSize]));
  try
  FillChar(sil,SizeOf(TSecurityImpersonationLevel),#0);
    snlogger.Log(Format('mem b: %d',[SNGetWorkingSetSize]));
  sil := SecurityIdentification;
    snlogger.Log(Format('mem c: %d',[SNGetWorkingSetSize]));
  if LogonUser(PAnsiChar(LUser),PAnsiChar(LDomain),PAnsiChar(LPassword),LOGON32_LOGON_INTERACTIVE,LOGON32_PROVIDER_DEFAULT,ltoken)then
    begin
    snlogger.Log(Format('mem d: %d',[SNGetWorkingSetSize]));

    if DuplicateTokenEx(ltoken,TOKEN_ALL_ACCESS,nil,sil,TokenPrimary,ltoken)then
    begin
    snlogger.Log(Format('mem e: %d',[SNGetWorkingSetSize]));
    fillchar(pi,sizeof(TProfileInfo),#0);
    pi.dwSize:=sizeof(TProfileInfo);
    pi.lpUserName:=PAnsiChar(LUser);
    if(LoadUserProfile(ltoken,pi))then
      begin
    snlogger.Log(Format('mem f: %d',[SNGetWorkingSetSize]));
      if (CreateEnvironmentBlock(
        lenv,
        ltoken,
        false
      ))then
        begin
    snlogger.Log(Format('mem g: %d',[SNGetWorkingSetSize]));
        FillChar(pri,sizeof(_PROCESS_INFORMATION),#0);
        ZeroMemory(@si,sizeof(si));
        if not(CreateProcessAsUser(
            ltoken,
            nil,
            PAnsiChar(LProgram),//PChar(SN_PATH+SN_PROG+' -0000000 -q'),
            nil,
            nil,
            false,
            CREATE_UNICODE_ENVIRONMENT or CREATE_NEW_PROCESS_GROUP or NORMAL_PRIORITY_CLASS or CREATE_NO_WINDOW, //TODO: Priorität einstellen?
            lenv,
            nil,
            si,
            pri
            ))then
          SNLogger.Log('Prozess konnte nicht gestartet werden. '+SysErrorMessage(GetLastError),ltBoth);
    snlogger.Log(Format('mem h: %d',[SNGetWorkingSetSize]));
        if not DestroyEnvironmentBlock(lenv)then snlogger.Log('EnvironmentBlock konnte nicht geschlossen werden');
        if not UnloadUserProfile(ltoken,pi.hProfile)then snlogger.Log('UserProfile konnte nicht geschlossen werden');
        if not CloseHandle(pri.hProcess)then snlogger.Log('hProcess konnte nicht geschlossen werden');
        if not CloseHandle(pri.hThread)then snlogger.Log('hThread konnte nicht geschlossen werden');
        if not CloseHandle(ltoken)then snlogger.Log('ltoken konnte nicht geschlossen werden');
    snlogger.Log(Format('mem i: %d',[SNGetWorkingSetSize]));

        //snlogger.log(inttostr(GetLastError));
        end else SNLogger.Log('Arbeitsumgebung konnte nicht erstellt werden. '+SysErrorMessage(GetLastError));
      end else SNLogger.Log('Benutzerprofil konnte nicht geladen werden. '+SysErrorMessage(GetLastError));
    end else SNLogger.Log('Duplicate nicht möglich. '+SysErrorMessage(GetLastError));
  end else SNLogger.Log('Login nicht möglich. '+SysErrorMessage(GetLastError),ltBoth);
except
  on e : exception do
    SNLogger.Log('Fehler beim Starten eines Prozesses:'+e.Message+slinebreak+SysErrorMessage(GetLastError),ltBoth);
  end;
finally
snlogger.log(syserrormessage(getlasterror));
    snlogger.Log(Format('mem j: %d',[SNGetWorkingSetSize]));
end;
end;
SNGetWorkingSetSize ist diese Methode: http://www.delphipraxis.net/internal...=218154#218154

Diese snlogger.log Methode schreibt mir den angegebenen String in ne Datei, da hab ich unter anderem folgendes:

Zitat:
03.11.2009 09:59:42: 3200 mem a: 7800
03.11.2009 09:59:42: 3200 mem b: 7800
03.11.2009 09:59:42: 3200 mem c: 7800
03.11.2009 09:59:42: 3200 mem d: 7812
03.11.2009 09:59:42: 3200 mem e: 7812
03.11.2009 09:59:42: 3200 mem f: 7856
03.11.2009 09:59:42: 3200 mem g: 7984
03.11.2009 09:59:42: 3200 mem h: 8128
03.11.2009 09:59:42: 3200 mem i: 8128
03.11.2009 09:59:42: 3200 Der Vorgang wurde erfolgreich beendet
03.11.2009 09:59:42: 3200 mem j: 8132


Das Problem eben ist, dass der Speicher nicht freigegeben wird und der Dienst irgendwann abstürzt.
Das CreateEnvironmentBlock scheint hierbei am meisten Speicher zu fressen.

Wenn ich das recht sehe, hab ich hier tokens und records, wie gebe ich die denn frei?
Oder übersehe ich ein Objekt das ich nicht freigebe?

Diese Suche anch Speicherlecks ist echt zermürbend
Martin Weber
Ich bin ein Rüsselmops
  Mit Zitat antworten Zitat
Assertor

Registriert seit: 4. Feb 2006
Ort: Hamburg
1.296 Beiträge
 
Turbo C++
 
#2

Re: Speicherfresser CreateProcess?

  Alt 3. Nov 2009, 10:35
Hi,

ich frage mich, warum immer das Working Set als Maßstab verwendet wird: Das Working Set ist abhängig von anderen Anwendungen auf dem System und laufenden Anwendungen im Vorder- und Hintergrund. (hier egal) Auch das Minimieren von Fenstern verändert das Working Set.

So würde ich auf jeden Fall nicht nach Speicherlecks suchen.

Spricht etwas dagegen mit FastMM4 im FullDebugMode anzufangen, und die enthaltenen Log-Funktion zu nutzen?

Wenn das nicht hilft, kannst Du vor und nach kritischen Geschichten ein "ScanMemoryPoolForCorruptions" (so oder ähnlich, gerade kein Delphi an) von FastMM aufrufen.

Nächster Schritt wäre für mich dann eine Kontrolle der Handles, z.B. mit Tools von SysInternals oder AQtime. Auch manche Exception Tracker sind hilfreich (madExcept, EurekaLog etc).

Aber das Working Set bestimmt nicht...

Gruß Assertor
Frederik
  Mit Zitat antworten Zitat
Angel4585

Registriert seit: 4. Okt 2005
Ort: i.d.N.v. Freiburg im Breisgau
2.199 Beiträge
 
Delphi 2010 Professional
 
#3

Re: Speicherfresser CreateProcess?

  Alt 3. Nov 2009, 10:48
Danke für die Anwort.

FastMM4 hab ich bereits im FullDebugMode aktiv, liefert mir aber - seit ich einige Löcher gestopft hab - beim Beenden vom Dienst kein Logfile(mehr).
Im Taskmanager sehe ich aber, dass der Speicherverbrauch immernoch steigt und steigt.

Dieses ScanMemoryPoolForCorruptions werd ich mal testen, danke.

Wenn ich damit auch nix finde schau ich mir noch die anderen Sachen an.

Edit: Woah innerhalb von 5 Sekunden hab ich ne 11 mb große Datei durch das ScanMemoryPoolForCorruptions bekommen
Martin Weber
Ich bin ein Rüsselmops
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#4

Re: Speicherfresser CreateProcess?

  Alt 3. Nov 2009, 11:00
Zitat von Angel4585:
Im Taskmanager sehe ich aber, dass der Speicherverbrauch immernoch steigt und steigt.
Es gibt nicht den einen Speicherverbrauch. Welchen meinst du also?
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Angel4585

Registriert seit: 4. Okt 2005
Ort: i.d.N.v. Freiburg im Breisgau
2.199 Beiträge
 
Delphi 2010 Professional
 
#5

Re: Speicherfresser CreateProcess?

  Alt 3. Nov 2009, 11:17
Also unter Vista hat die Spalte die Beschriftung "Arbeitsspeicher (privater Arbeitssatz)".
Unter XP schau ich bei "Speicherauslastung".

Oder schau ich ander falschen Stelle?

Edit: Ich werd mir das mal mit dem ProcessExplorer von sysinternals anschauen, da sieht man das etwas detaillierter
Martin Weber
Ich bin ein Rüsselmops
  Mit Zitat antworten Zitat
Angel4585

Registriert seit: 4. Okt 2005
Ort: i.d.N.v. Freiburg im Breisgau
2.199 Beiträge
 
Delphi 2010 Professional
 
#6

Re: Speicherfresser CreateProcess?

  Alt 3. Nov 2009, 13:14
Sorry für Doppelpost..

Also im ProcessExplorer seh ich beim Physical Memory, dass das Working Set Private immer weiter ansteigt.
Das Working Set Shareable bleibt konstant.

Beim Virtual Memory steigen die Private Bytes auch immer mehr. Hier hab ich auch Page Faults, die aber soweit ich weis nicht direkt was mit dem freigeben von Speicher zu tun haben.

Edit: Kann ich denn irgendwie von den Speicherzahlen rausfinden um was genau es sich handelt, nicht freigegebene Objekte oder was anderes?

Edit2: Laut Process Explorer steigt die Anzahl der Handles auch an, anfangs bei 180, sind es jetzt schon 220.
Martin Weber
Ich bin ein Rüsselmops
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.275 Beiträge
 
Delphi 10.4 Sydney
 
#7

Re: Speicherfresser CreateProcess?

  Alt 3. Nov 2009, 15:08
Hallo,

hast du die Methode mal separat (neues, leeres Projekt)
mit FastMM4 oder memcheck geprüft ?


Heiko
Heiko
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.275 Beiträge
 
Delphi 10.4 Sydney
 
#8

Re: Speicherfresser CreateProcess?

  Alt 3. Nov 2009, 15:12
Hallo,

if DuplicateTokenEx(ltoken,TOKEN_ALL_ACCESS,nil,sil,TokenPrimary,ltoken)then Wird hier nicht das Original-Token ltoken überschrieben ?

Mach doch mal sowas.

if DuplicateTokenEx(ltoken,TOKEN_ALL_ACCESS,nil,sil,TokenPrimary,ltoken2)then
Heiko
Heiko
  Mit Zitat antworten Zitat
Angel4585

Registriert seit: 4. Okt 2005
Ort: i.d.N.v. Freiburg im Breisgau
2.199 Beiträge
 
Delphi 2010 Professional
 
#9

Re: Speicherfresser CreateProcess?

  Alt 4. Nov 2009, 14:33
hoika du bist ein Speichergott

Das scheints gewesen zu sein

Jetz hab ich nur das Problem, dass ich ab und zu folgende Meldung bekomm: "Diese Sicherheitskennung kann nicht als Besitzer des Objekts zugeordnet werden"

Das seltsame daran, er sagt er kann das CreateProcessAsUser ausführen, also das liefert ein true zurück, gestartet wurde allerdings nix, das GetLastError bringt dann die Meldung...

Soll ich dafür en eigenen Thread aufmachen?
Martin Weber
Ich bin ein Rüsselmops
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:47 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz