Process Explorer / Handle / VMMap in der Praxis — Hängern, Lecks und „Datei wird verwendet“ vom aktuellen Zustand aus nachjagen

· · Sysinternals, Process Explorer, VMMap, Handle-Leck, Speicherleck, Störungsanalyse, Windows, Langlaufende Prozesse

„Ein Neustart am Montagmorgen behebt es.“ — Diesen Satz habe ich in Wartungsberatungen für geräteintegrierte Anwendungen immer wieder gehört. Direkt nach dem Start läuft alles einwandfrei, doch etwa Donnerstag wird das Wechseln zwischen Bildschirmen träge, und am Freitagabend braucht ein Tastendruck mehrere Sekunden, bis eine Reaktion erfolgt. Gelegentlich taucht ein noch nie zuvor gesehener „ungültiges Handle“-Fehler auf. Und ein Neustart behebt es, als wäre nichts gewesen. Ist dieser Punkt einmal erreicht, pendelt sich der Betrieb bei „jede Woche neu starten“ ein, und es vergehen Jahre, ohne dass jemand die eigentliche Ursache kennt.

Zur Ursache solcher Symptome gelangen Sie nie, wenn Sie nur Protokolle anstarren. Was Sie brauchen, ist ein direkter Blick darauf, was und wie viel dieser Prozess genau in diesem Moment hält. Im vorherigen Artikel, „Ein praktischer Leitfaden zu Process Monitor (ProcMon)“, haben wir ProcMon behandelt, das die Zeitleiste von Vorgängen aufzeichnet. Diesmal, als Fortsetzung und Teil zwei der praxisnahen Sysinternals-Serie, ordnen wir die Werkzeuge auf der Seite des ZustandsProcess Explorer, Handle und VMMap — rund um die drei großen Symptome langlaufender Anwendungen: „es wird immer langsamer“, „die Datei lässt sich nicht löschen“ und „es hängt“.

1. Das Wichtigste zuerst

  • ProcMon ist „Geschichte“, Process Explorer ist „jetzt“. Process Explorer erlaubt es, die von jedem Prozess geöffneten Handles und geladenen DLLs aufzulisten und zu durchsuchen, und Microsoft stellt ausdrücklich fest, dass es sich für die Untersuchung von DLL-Versionsproblemen und Handle-Lecks eignet.1
  • Für „die Datei lässt sich nicht löschen oder ersetzen“ ist Find Handle or DLL (Strg+F) der schnellste Weg. Suchen Sie nach einem Teil des Pfads, und Sie identifizieren den haltenden Prozess in Sekunden (Abschnitt 3).
  • Für „es hängt“ öffnen Sie die Prozesseigenschaften → den Tab Threads und betrachten die Thread-Stacks. Ohne Symbolkonfiguration (dbghelp.dll und ein Symbolpfad) erhalten Sie jedoch nur eine Liste von Adressen (Abschnitt 4).12
  • Für „es wird immer langsamer“ Spalten hinzufügen und die Steigung beobachten. Fügen Sie die vier Spalten Handle Count, USER Objects, GDI Objects und Private Bytes hinzu und suchen Sie nach denen, die im Zeitverlauf stetig steigen. GDI-/USER-Objekte haben ein Limit pro Prozess, und ist es erreicht, beginnen Zeichnen und Fensterstellung zu versagen (Abschnitt 5).3
  • Die CLI-Version, handle.exe, eignet sich für skriptgesteuerte, regelmäßige Überwachung. handle -s -p <Prozess> erlaubt es, Handle-Anzahlen nach Typ nach einem Zeitplan aufzuzeichnen. Das erzwungene Schließen von Handles mit -c wird offiziell als destabilisierend gewarnt, deshalb verwenden wir es normalerweise nicht.4
  • Für „Private Bytes wächst immer weiter“ die Zusammensetzung mit VMMap aufschlüsseln. Heap bedeutet nativ, Managed Heap bedeutet .NET — entscheiden Sie zuerst, in welcher Arena der Übeltäter steckt, und wechseln Sie dann zum jeweils passenden Spezialwerkzeug (Abschnitt 6).5
  • Wenn eher betriebssystemweiter Speicher als ein einzelner Prozess verdächtig wirkt, verwenden Sie RAMMap.6 Für Abstürze wechseln Sie zur Aufzeichnung eines Dumps mit ProcDump („Eine Einführung in das Sammeln von Windows-Absturz-Dumps“).
  • Keines dieser Werkzeuge muss installiert werden, und sie lassen sich direkt aus Sysinternals Live ausführen. Das macht es leicht, sie auf einen Offline-Geräte-PC mitzunehmen — aber allein die Symbole benötigen vorherige Vorbereitung (Abschnitt 8).7

2. Process Explorer Grundlagen — Als Administrator ausführen, den Task-Manager ersetzen und den Bildschirm lesen

Process Explorer benötigt keine Installation: Entpacken Sie das ZIP und führen Sie procexp.exe aus (unter 64-Bit läuft procexp64 automatisch).1 Weil es sich um ein Werkzeug handelt, das in die Prozesse und Dienste anderer Benutzer hineinschaut, sollten Sie es bei einer Untersuchung stets „Als Administrator ausführen“. Starten Sie es mit Standardrechten, kommt genau der Prozess, an dem Sie interessiert sind, mit „Zugriff verweigert“ zurück, ohne dass Stacks oder Handles sichtbar wären.

Auf dem Rechner eines Untersuchenden führt das Aktivieren von Optionen → Task-Manager ersetzen dazu, dass Strg+Umschalt+Esc und jeder Aufruf des Task-Managers über die Taskleiste stattdessen Process Explorer öffnet. Der Effekt von „das gewohnte Werkzeug öffnet sich, wenn Sie es eilig brauchen“ ist unauffällig, aber bedeutsam, und wir haben es auf jedem Entwicklungsrechner hier ausgetauscht (derselbe Menüpunkt macht es rückgängig).

Der Bildschirm ist ein zweigeteiltes Layout: der Prozessbaum oben, Details zum ausgewählten Prozess darunter. Verwenden Sie Ansicht → Lower Pane View, um den unteren Bereich zwischen der Handles-Ansicht (einer Liste offener Handles) und der DLLs-Ansicht (einer Liste geladener DLLs und speicherabgebildeter Dateien) umzuschalten.1 Als Erstes sollten Sie lernen, was die Zeilenfarben bedeuten (Sie können sie unter Optionen → Configure Colors prüfen und ändern).

Farbe (Standard) Bedeutung
Grün Neu gestarteter Prozess (standardmäßig etwa eine Sekunde)
Rot Prozess mitten im Beenden
Hellblau Unter dem eigenen Benutzerkonto laufender Prozess
Pink Prozess, der einen Dienst hostet
Violett Vermutlich gepackte (komprimierte/verschleierte) ausführbare Datei
Dunkelgrau Angehaltener Prozess

Auffälligkeiten wie „ein Prozess wird grün geboren, wird sofort rot und verschwindet, immer wieder“ lassen sich allein an Baumansicht und Farbcodierung erkennen. Da Eltern-Kind-Beziehungen zwischen Prozessen im Baum sichtbar sind, ist außerdem sofort klar, „wessen Kind ist dieses conhost.exe“ und „wird die Anwendung von einem Dienst oder von der Aufgabenplanung gestartet“.

3. „Die Datei wird verwendet und lässt sich nicht löschen“ — den Übeltäter mit Find Handle or DLL identifizieren

„Die Protokolldatei lässt sich nicht löschen.“ „Ich wollte aktualisieren, und die exe wird verwendet.“ „Der USB-Stick lässt sich nicht sicher auswerfen.“ — Die Untersuchung dieses Symptoms endet bei Find → Find Handle or DLL (Strg+F). Geben Sie einen Teil eines Datei- oder Ordnernamens ein (etwa report.csv oder D:\Data) und suchen Sie, und Sie erhalten eine Liste von Prozessen, die ein Handle mit diesem Namen geöffnet haben oder diese DLL geladen haben.1 Klicken Sie auf eine Ergebniszeile, wird der entsprechende Prozess im oberen Bereich ausgewählt, mit dem zugehörigen Handle im unteren Bereich hervorgehoben.

Ist der Prozess gefunden, ist die richtige Reaktion, „diesen Prozess sauber zu beenden“. Sie können das Handle in Process Explorer auch mit der rechten Maustaste anklicken und mit Close Handle erzwungen schließen, aber aus demselben Grund wie bei handle -c unten empfehlen wir das im Produktivbetrieb nicht. Beachten Sie außerdem, dass nur benannte Objekte durchsucht werden können — unbenannte Events und Thread-Handles werden nicht gefunden.

Die DLLs-Ansicht wird auch verwendet, um zu bestätigen, „welche Version einer DLL, von welchem Ort, tatsächlich geladen wurde“. Um DLL-Versionsprobleme wie „es hielt noch eine alte DLL“ oder „die von mir verteilte korrigierte Version wird nicht gelesen“ zu prüfen, kombinieren Sie diesen Bildschirm mit der Untersuchung der Ladereihenfolge über ProcMon (Abschnitt 5.2 von Teil eins).

Wie man eine verwendete exe oder DLL überhaupt sicher austauscht, ist eine Design-, keine Untersuchungsfrage. Unser am selben Tag veröffentlichter Schwesterartikel, „Wie man eine exe oder DLL austauscht, die gerade verwendet wird“, behandelt das Design des Austauschs einschließlich Restart Manager — wenn Sie also selbst den Update-Mechanismus bauen, lesen Sie dort weiter.

4. „Es hängt“ — Thread-Stacks im Tab Threads lesen

Das Fenster ist weiß geworden und reagiert nicht mehr. Bevor Sie es zwangsweise beenden, doppelklicken Sie auf den Prozess, um seine Eigenschaften zu öffnen, und betrachten den Tab Threads. Er listet CPU-Nutzung, Zyklenzahl und Startadresse pro Thread auf, und wählt man einen Thread aus und drückt die Schaltfläche Stack, zeigt sich, in welchem Funktionsaufruf dieser Thread gerade angehalten ist. Die meisten Hänger sind „der UI-Thread wartet auf etwas“, sehen Sie also WaitForSingleObject, EnterCriticalSection oder ein synchrones Warten auf Netzwerk- oder serielle E/A oben im Stack, ist das die unmittelbare Ursache.

Jedoch ist ohne konfigurierte Symbole der Stack nur eine Liste von Adressen und Modulname+0x1234-Einträgen und im Wesentlichen unlesbar. Konfigurieren Sie die folgenden zwei Punkte unter Optionen → Configure Symbols.

Dbghelp.dll-Pfad:
  C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\dbghelp.dll
  * Auf die mit WinDbg (Debugging Tools for Windows) ausgelieferte Datei zeigen

Symbols-Pfad:
  srv*C:\Symbols*https://msdl.microsoft.com/download/symbols
  * C:\Symbols ist der lokale Cache. Ab dem zweiten Mal wird von hier gelesen

Zwei zentrale Punkte sind wichtig. Erstens unterstützt die standardmäßige dbghelp.dll in System32 keinen Download von einem Symbolserver, weshalb Sie auf die mit WinDbg ausgelieferte Datei zeigen müssen. Zweitens: Wie die offizielle Dokumentation feststellt, muss bei Verwendung eines Symbolservers symsrv.dll am selben Ort wie die von Ihnen angegebene dbghelp.dll vorhanden sein (der Installationsordner von WinDbg enthält beide).1 Das Symbolpfadformat srv*Cache*ServerURL und der öffentliche Symbolserver von Microsoft https://msdl.microsoft.com/download/symbols sind derselbe Mechanismus, den auch WinDbg verwendet.2 Um die Stacks Ihrer eigenen Anwendung zu lesen, benötigen Sie außerdem die PDBs Ihres eigenen Builds, fügen Sie also den Ordner, der sie enthält, durch ein Semikolon getrennt zum Symbolpfad hinzu.

Bei .NET-Anwendungen sind die Stacks im Tab Threads nativ-Frame-zentriert, und verwaltete Methodennamen kommen möglicherweise nicht genau heraus. Wenn Sie ernsthaft einem verwalteten Hänger oder Deadlock nachjagen, ist es der zuverlässige Weg, während des Hängens einen Dump aufzuzeichnen und ihn mit WinDbg + SOS zu betrachten („Absturz-Dumps mit WinDbg + SOS lesen“). Die Arbeitsteilung lautet: Der Tab Threads ist das Werkzeug für „vor Ort in drei Minuten einen groben Eindruck bekommen“; ein Dump ist das Werkzeug für „mit nach Hause nehmen und klären“. Und bitte drücken Sie im Tab Threads gegen einen Produktivprozess nicht die Schaltflächen Kill/Suspend — was als Beobachtung gedacht war, wird zum Eingriff.

5. „Es wird immer langsamer“ — Lecks mit Handle Count, USER-/GDI-Spalten und handle.exe überwachen

Die klassischen Ursachen für Anwendungen, die sich im Langzeitbetrieb verschlechtern, sind Lecks von Handles, GDI-/USER-Objekten und Speicher. Process Explorer eignet sich hervorragend auch als Überwachungswerkzeug — fügen Sie die folgenden Spalten über Ansicht → Select Columns hinzu.

  • Tab Process PerformanceHandle Count (die Anzahl der Kernel-Objekt-Handles)
  • Tab Process MemoryPrivate Bytes, Virtual Size, USER Objects, GDI Objects

Was Sie betrachten, ist nicht der absolute Wert, sondern die Steigung. Bei einer gesunden Anwendung steigt und fällt die Handle-Anzahl mit der Aktivität, bleibt aber in einem festen Bereich; bei einem Leck steigt sie stetig — „bei jedem Vorgang nach oben, nie wieder herunter“. Schon das stündliche oder morgens-und-abends Anfertigen von Screenshots zeigt bis zum nächsten Tag den Trend. GDI-Objekte und USER-Objekte haben ein Limit pro Prozess (standardmäßig 10.000, änderbar über den Registrierungswert GDIProcessHandleQuota und Ähnliches) sowie ein theoretisches sitzungsweites Limit von 65.536; ist das Limit erreicht, beginnt das Erzeugen von Stiften, Pinseln und Fenstern zu scheitern.3 „Die Bildschirmdarstellung dreht freitags durch“ ist meist genau das.

Für Umgebungen, in denen Sie keine GUI öffnen können, oder für skriptgesteuerte regelmäßige Überwachung, verwenden Sie die CLI-Version, handle.exe. Es ist ein Kommandozeilenwerkzeug, das Handles auflistet und durchsucht, und es setzt Administratorrechte voraus.4

:: Wer diese Datei/diesen Ordner hält (Suche mit Teilnamen-Abgleich)
handle.exe /accepteula report.csv
handle.exe D:\Data

:: Alle Handle-Typen ausgeben, nicht nur Dateien, eingegrenzt nach Prozessname
handle.exe -a -p MyEquipApp

:: Handle-Anzahlen nach Typ aggregieren -- dies für regelmäßige Leck-Überwachung protokollieren
handle.exe -s -p MyEquipApp.exe >> C:\Logs\handles_%date:~0,4%%date:~5,2%%date:~8,2%.log

Hängen Sie die Ausgabe von -s (die Summen pro Typ wie Event: 1523, File: 88, …) stündlich über die Aufgabenplanung an, und Sie erhalten harte Zahlen dafür, „wie viele Handles welchen Typs pro Tag wachsen“, selbst auf einem Geräte-PC, den Sie nur remote warten können. Kennen Sie erst den Typ, schrumpft die Verdächtigenliste drastisch. Event bedeutet nicht freigegebene Events, File bedeutet vergessenes Schließen, Thread bedeutet zurückgelassene Handles nach Thread-Ende, und so weiter.

Beachten Sie, dass die Option -c ein angegebenes Handle erzwungen schließen kann, doch schon die offizielle Dokumentation warnt, dass das Schließen von Handles Anwendungs- oder Systeminstabilität verursachen kann.4 Unsere Richtlinie ist, es im Produktivbetrieb auch nicht als Notlösung zur Freigabe einer Sperre zu verwenden. Kennen Sie erst „welcher Typ leckt“, geht die Vorgehensweise, um zu identifizieren, „welcher Code das zugewiesen hat“, weiter in „Untersuchung von Langzeitabstürzen einer Anwendung für Industriekameras - Das Handle-Leck (Teil 1)“ und „Ein Fundament für Windows-Fehlerpfad-Tests mit Application Verifier aufbauen“.

6. VMMap — „Private Bytes wächst immer weiter“ aufschlüsseln

Handle-Anzahlen sind flach, aber allein Private Bytes wächst immer weiter — dann öffnen Sie VMMap. Es ist ein Werkzeug, das den virtuellen und physischen Speicher (den Arbeitsspeicher) eines Prozesses analysiert und den zugesagten virtuellen Speicher nach Typ aufgeschlüsselt anzeigt.5 Starten Sie es, wählen Sie den Zielprozess, und Sie erhalten oben eine farbcodierte Zusammenfassung und darunter eine detaillierte Speicherkarte. So lesen Sie die wichtigsten Kategorien.

Kategorie Was sie enthält Typischer Übeltäter bei stetigem Wachstum
Image Die EXE-/DLL-Körper selbst Plugin-DLLs, die geladen bleiben
Heap Nativer Heap (new/malloc/HeapAlloc) C/C++-Code, Geräte-SDKs, Interop-Code, der nicht freigibt
Managed Heap Der .NET-GC-Heap Verwaltete Referenz-Lecks (Ereignishandler und Ähnliches)
Private Data Direkte Zuweisung über VirtualAlloc usw. Bild-Framepuffer, SDK-interne Puffer
Stack Thread-Stacks Erstellte und nie aufgeräumte Threads
Shareable / Mapped File Gemeinsam genutzter Speicher, abgebildete Dateien Nicht freigegebene prozessübergreifende Abschnitte

Das Nutzungsmuster lautet: „Aktualisieren Sie den Snapshot mit F5, während Sie den problematischen Vorgang wiederholen, und beobachten Sie, welche Kategorie wächst.“ VMMap unterstützt den Vergleich von Snapshots, eine Zeitleistenansicht und den Export von Ergebnissen,5 sodass Sie vor Ort Nachweise sammeln können wie „über 100 Messungen hinweg wuchs Heap um 40 MB, während Managed Heap flach blieb“. Ist die Arena entschieden, geht es weiter zu den Spezialwerkzeugen: Managed Heap bedeutet Untersuchung auf .NET-Seite („„Langsam“ mit PerfView und dotnet-trace eingrenzen“), Heap/Private Data bedeutet Untersuchung auf nativer Seite (Application Verifier, Dump-Analyse). Diese Eingrenzung zu überspringen und direkt der GC die Schuld zu geben, wobei mehrere Tage verbrannt werden, ist der mit Abstand häufigste Umweg bei Geräteanwendungen, die aus .NET plus einem nativen SDK gebaut sind.

Bei 32-Bit-Prozessen lohnt sich außerdem die Beobachtung der Fragmentierung. Die Fragmentation View zeigt, wie der freie Platz im Adressraum verstreut ist, und visualisiert Zustände wie „Free summiert sich auf mehrere hundert MB, aber der größte zusammenhängende freie Block (Largest) beträgt nur einige Dutzend MB“. „Es sollte doch Speicher verfügbar sein, und trotzdem bekommen wir OutOfMemory“ und „nur die Zuweisung eines großen Bildpuffers scheitert“ laufen meist darauf hinaus, und es liefert solide Belege für Gegenmaßnahmen (auf 64-Bit umsteigen, ein Redesign zur Wiederverwendung von Puffern).

Wenn eher betriebssystemweiter Speicher als ein einzelner Prozess verdächtig wirkt (kein Prozess ist fett, und trotzdem geht der Speicher aus), wechseln Sie zu RAMMap, das nach Tabs aufgeschlüsselt zeigt, wofür der gesamte physische Speicher verwendet wird. Es legt auch Dateicache, Treiber und Kernel-Nutzung offen, sodass dies der Ort ist, an dem Sie nach „einem Übeltäter außerhalb der Anwendung“ suchen.6

7. Fallstudie — „Der Geräte-PC, der jeden Freitag langsam wird“ triagieren

Hier ist, wie der Geräte-PC aus der Einleitung tatsächlich mit den bisherigen Werkzeugen trianiert wird. Weil der Betrieb ihn Montagmorgen neu startet, ist Freitag „Tag fünf des Betriebs“. Mit anderen Worten lautet die Ausgangshypothese, dass etwas proportional zur Zeit wächst.

  1. Etwa Mittwoch Process Explorer installieren und die Spalten einrichten. Fügen Sie Handle Count, USER Objects, GDI Objects und Private Bytes hinzu und protokollieren Sie die Werte des Zielprozesses. Registrieren Sie gleichzeitig ein stündliches handle -s -p TargetApp.exe-Protokoll über die Aufgabenplanung (Abschnitt 5).
  2. Am nächsten Tag die Steigung betrachten. In diesem Fall wuchs Handle Count um rund 20.000 an einem Tag, und das Protokoll nach Typ zeigte monoton steigende Event-Handles. Private Bytes und GDI/USER waren im Wesentlichen flach. An diesem Punkt schrumpft die Verdächtigenliste auf „nicht freigegebene Kernel-Objekte (Events)“.
  3. Das Original in der Handles-Ansicht betrachten. Sortieren Sie die Handles-Ansicht im unteren Bereich nach Type, und es gibt Zehntausende unbenannte Events. Weil sie unbenannt sind, lassen sie sich mit Find Handle nicht verfolgen, aber Typ und Wachstumsrate zu kennen genügt. Aus der Übereinstimmung mit dem Messzyklus (in diesem Fall zwei pro Geräte-Pollingrunde) entstand die Hypothese, dass die Kommunikationsbibliothek ihre Warte-Events nicht freigibt, und eine Codeüberprüfung bestätigte sie. Möchten Sie die Zuweisungsstelle mit einem Werkzeug bestimmen, kommen hier Application Verifier und !htrace ins Spiel.
  4. Wäre Private Bytes gewachsen, würden Sie statt Schritt 3 die Zusammensetzung in VMMap aufschlüsseln (Abschnitt 6) und zu nativer Untersuchung bei Heap oder .NET-Untersuchung bei Managed Heap verzweigen.
  5. Würde keine der Zahlen wachsen und es hängt nur, betrachten Sie die Stacks im Tab Threads (Abschnitt 4) und identifizieren, worauf gewartet wird.

Der entscheidende Punkt ist, den Beleg „die Steigung des Graphen“ zu sichern, bevor Sie irgendetwas beheben. Nehmen Sie nach der Behebung dieselbe Messung erneut vor und zeigen Sie, dass die Steigung null ist, und Sie können „es ist behoben“ mit Zahlen belegen. Bei Langzeitproblemen, bei denen das Warten auf eine Reproduktion Tage dauert, ist das Einrichten dieser Messung die Untersuchung.

8. Werkzeuge auf Produktiv-PCs mitbringen und betriebliche Vorsichtsmaßnahmen — Sysinternals Live, EULAs und Offline-Symbole

Alle Sysinternals-Werkzeuge sind eigenständige ausführbare Dateien, die keine Installation benötigen, sodass es genügt, das ZIP auf einem USB-Stick mitzubringen, um sie auszuführen. Beim ersten Start erscheint ein EULA-Zustimmungsdialog, akzeptieren Sie ihn also für unbeaufsichtigte Läufe oder aus einem Skript heraus ausdrücklich mit dem Schalter /accepteula. Ist das Netzwerk verfügbar, erlaubt Ihnen der Dienst Sysinternals Live, sie direkt ohne Download auszuführen, über eine URL wie https://live.sysinternals.com/procexp.exe oder einen UNC-Pfad wie \\live.sysinternals.com\tools\<Werkzeugname>.7 Das ist der schnellste Weg, wenn Sie sich diesen einen Rechner jetzt sofort ansehen möchten.

Was Sie auf einem Offline-Geräte-PC ins Stolpern bringt, sind Symbole (die Stack-Anzeige aus Abschnitt 4 ist unbenutzbar). Es gibt zwei Antworten: (1) einen Entwicklungsrechner mit Internetzugang Symbole gegen denselben OS-Build auflösen lassen, den gesamten lokalen Cache (C:\Symbols) auf den Geräte-PC kopieren und den Symbolpfad ausschließlich auf diesen lokalen Ordner richten; oder (2) auf Stack-Analyse verzichten, sich vor Ort auf das Aufzeichnen von Dumps (ProcDump) und das Protokollieren von Zahlen beschränken und diese zur Analyse auf einen Entwicklungsrechner mitnehmen. Option (2) ist die zuverlässigere, und wie man Dumps aufzeichnet, wird in „Eine Einführung in das Sammeln von Windows-Absturz-Dumps“ behandelt.

Zuletzt zur betrieblichen Seite. Die Beobachtung mit Process Explorer oder VMMap ist niedriglastig und risikoarm, aber eingreifende Vorgänge — das Beenden oder Anhalten eines Prozesses, das Beenden eines Threads, Close Handle, handle -c — sollten im Produktivbetrieb grundsätzlich untersagt sein. Führen Sie es, wie schon bei ProcMon in Teil eins, über denselben Freigabeprozess wie jede andere Änderung durch und legen Sie vorab fest, „wer was wann beobachtet und was nicht angefasst wird“, bevor Sie beginnen.

9. Standardpraxis (Entscheidungstabelle)

Symptom Zu verwendendes Werkzeug Worauf zu achten ist
Wird nach ein paar Tagen immer langsamer / instabil Process Explorer Die Steigung der Spalten Handle Count / USER & GDI Objects / Private Bytes (Abschnitt 5)
Eine Datei lässt sich nicht löschen oder ersetzen Process Explorer / handle.exe Nach Pfad suchen mit Find Handle or DLL (Strg+F) → der haltende Prozess (Abschnitt 3)
Hänger / reagiert nicht Process Explorer Eigenschaften → Tab Threads → Thread-Stacks (Symbole erforderlich, Abschnitt 4)
Private Bytes wächst immer weiter VMMap Welche der Kategorien Heap / Managed Heap / Private Data wächst (Abschnitt 6)
Speicher wird knapp, obwohl kein Prozess fett ist RAMMap Physische Speichernutzung über Use Counts und File Summary6
Absturz / Beenden mit Ausnahme ProcDump + WinDbg Dump-SammlungWinDbg + SOS
Wohin die CPU-Zeit geht / .NET-GC PerfView / dotnet-trace Quantitative Untersuchung von „es ist langsam“
Zeitleiste von Vorgängen (welche Datei, wann, in welcher Reihenfolge) Process Monitor Teil eins

10. Zusammenfassung

  • Während ProcMon „die Geschichte der Vorgänge“ aufzeichnet, sind Process Explorer / Handle / VMMap Werkzeuge, um „den Zustand in genau diesem Moment“ zu sehen. Die Untersuchung langlaufender Anwendungen braucht beides.
  • „Die Datei lässt sich nicht löschen“ dauert mit Find Handle or DLL (Strg+F) Sekunden; „es hängt“ erhält einen ersten Eindruck aus den Stacks im Tab Threads. Das Lesen von Stacks setzt die Konfiguration von dbghelp.dll (von einem Ort, an dem auch symsrv.dll liegt) und eines Symbolpfads voraus.
  • Fügen Sie für „es wird immer langsamer“ die Spalten Handle Count, USER/GDI Objects und Private Bytes hinzu und beobachten Sie die Steigung. Ein geplantes handle -s-Protokoll liefert Ihnen auch auf einem Geräte-PC ohne GUI-Zugang Zahlen.
  • Wachstum bei Private Bytes sollte in VMMap zunächst in Heap (nativ) / Managed Heap (.NET) / Private Data eingegrenzt werden, bevor Sie zum jeweiligen Spezialwerkzeug wechseln. Bei 32-Bit-Prozessen sollten Sie auch Fragmentierung in Verdacht ziehen.
  • Erzwungenes Schließen mit handle -c oder Close Handle ist eine Quelle von Instabilität, genau wie Microsoft warnt. Bleiben Sie im Produktivbetrieb bei der Beobachtung — greifen Sie nicht ein, oder holen Sie zuerst eine Freigabe ein, wenn Sie es müssen.
  • Die Werkzeuge sind eigenständig und leicht mitzubringen, und Sysinternals Live erlaubt es sogar, sie direkt auszuführen. Gleichen Sie das in Offline-Umgebungen aus, indem Sie Symbole vorab zwischenspeichern oder einen Dump mit nach Hause nehmen.

Verwandte Artikel

Verwandte Beratungsbereiche

KomuraSoft LLC übernimmt Leck-Untersuchungen für Geschäfts- und geräteintegrierte Anwendungen, die sich im Langzeitbetrieb verschlechtern, die Ursachenanalyse von Vor-Ort-Störungen wie Hängern und „Datei wird verwendet“, sowie die Einrichtung von Verfahren zur Nachweissammlung zusammen mit Korrekturen, die ein erneutes Auftreten verhindern.

</content>

  1. Microsoft Learn, Process Explorer - Sysinternals. Dazu, dass Process Explorer die geöffneten Handles eines Prozesses sowie dessen geladene DLLs und speicherabgebildete Dateien in zwei Bereichen anzeigt (Handle-Modus / DLL-Modus); dazu, dass sich der Prozess suchen lässt, der ein bestimmtes Handle oder eine DLL hält; dazu, dass es nützlich ist, um DLL-Versionsprobleme und Handle-Lecks aufzuspüren; dazu, dass symsrv.dll bei Verwendung eines Symbolservers am selben Ort wie dbghelp.dll vorhanden sein muss; sowie dazu, dass es sich direkt aus Sysinternals Live ausführen lässt.  2 3 4 5 6

  2. Microsoft Learn, Microsoft Public Symbol Server. Dazu, dass sich der Symbolpfad des öffentlichen Symbolservers von Microsoft in der Form srvlokaler Cachehttps://msdl.microsoft.com/download/symbols angeben lässt, sowie dazu, dass der nachgelagerte Speicher (lokaler Cache) nur die einmal abgerufenen Symbole vorhält, sodass nachfolgende Lesevorgänge aus der lokalen Kopie erfolgen.  2

  3. Microsoft Learn, GDI Objects. Dazu, dass GDI-Handles ein theoretisches Limit von 65.536 pro Sitzung haben, sowie dazu, dass es ein Standardlimit pro Prozess gibt, das über den Registrierungswert GDIProcessHandleQuota (im Bereich 256 bis 65.536) geändert werden kann.  2

  4. Microsoft Learn, Handle - Sysinternals. Dazu, dass handle.exe ein Kommandozeilenwerkzeug ist, das Informationen über offene Handles anzeigt und Administratorrechte voraussetzt; zum Abgleich von Teilnamen; dazu, dass -a alle Handle-Typen abdeckt; dazu, dass -p nach Prozess eingrenzt; dazu, dass -s Handle-Anzahlen nach Typ aggregiert; sowie dazu, dass -c Handles schließen kann, mit dem Hinweis, dass dies „Anwendungs- oder Systeminstabilität verursachen kann“.  2 3

  5. Microsoft Learn, VMMap - Sysinternals. Dazu, dass VMMap ein Analysewerkzeug für virtuellen und physischen Speicher eines Prozesses ist, das eine Aufschlüsselung des zugesagten virtuellen Speichers nach Typ zusammen mit dem jedem Typ zugewiesenen physischen Speicher (Arbeitsspeicher) zeigt; zu seinen Filter- und Aktualisierungsfunktionen (Snapshot); sowie zur Unterstützung des Datenexports und der Skriptsteuerung über Kommandozeilenoptionen.  2 3

  6. Microsoft Learn, RAMMap - Sysinternals. Dazu, dass RAMMap ein Werkzeug zur Analyse der betriebssystemweiten physischen Speichernutzung ist, das über Tabs wie Use Counts (Summen nach Typ), Processes (Arbeitsspeicher der Prozesse) und File Summary (im RAM residente Dateidaten) zeigt, wofür der Speicher verwendet wird; sowie zur Unterstützung des Speicherns und Ladens von Snapshots.  2 3

  7. Microsoft Learn, Sysinternals. Dazu, dass Sysinternals Live ein Dienst ist, der es erlaubt, Werkzeuge ohne Download direkt über eine URL live.sysinternals.com/ oder einen Pfad \\live.sysinternals.com\tools\ auszuführen, sowie dazu, dass sich die Werkzeugliste unter live.sysinternals.com durchsuchen lässt.  2

Aktuelle Artikel mit denselben Schlagwörtern führen zu verwandten Themen weiter.

Diese Seiten ordnen den Artikel in einen größeren Leistungs- und Entscheidungskontext ein.

Dieser Artikel ist direkt mit den folgenden Leistungen verbunden.

Häufige Fragen

Fragen, die in Beratungen zu diesem Artikelthema häufig gestellt werden.

Der Task-Manager existiert doch bereits — warum sich die Mühe mit Process Explorer machen?
Weil der Task-Manager nicht zeigt, welcher Prozess welche Datei oder welches Objekt geöffnet hält, oder an welcher Stelle im Code jeder einzelne Thread gerade angehalten ist. Process Explorer listet Handles und DLLs pro Prozess auf, durchsucht Handles nach Namen (Strg+F) und zeigt Thread-Stacks an, was Untersuchungen von „die Datei lässt sich nicht löschen“ und „es hängt“ auf ein völlig anderes Niveau als der Task-Manager hebt. Fügen Sie Spalten für Handle-Anzahl und USER-/GDI-Objektanzahl hinzu, dient es zusätzlich als Leck-Überwachungswerkzeug. Aktivieren Sie im Menü Optionen die Funktion Task-Manager ersetzen, wird jeder Aufruf des Task-Managers durch Process Explorer ersetzt, sodass es auf dem Rechner eines Untersuchenden praktisch ist, ihn einfach auszutauschen.
Wenn ich mit der Option -c von handle.exe ein Handle schließe, kann ich eine Dateisperre dann sofort aufheben?
Technisch ja, aber im Produktivbetrieb sollten Sie es grundsätzlich nicht tun. Schon die offizielle Dokumentation warnt davor, dass das Schließen von Handles Anwendungs- oder Systeminstabilität verursachen kann. Es entreißt von außen ein Handle, ohne den internen Zustand des Prozesses zu berücksichtigen, sodass der ungünstigste Unfall durchaus möglich ist: Sobald dieser Prozess dasselbe Handle später erneut verwendet, zeigt es auf ein anderes Objekt, und es kommt zu Fehlverhalten (Wiederverwendung von Handle-Werten). Der richtige Ansatz ist, den haltenden Prozess zu identifizieren und ihn sauber zu beenden. Geht es um den Austausch einer verwendeten exe oder DLL, erwägen Sie eine Lösung auf Design-Ebene wie Restart Manager.
Private Bytes wachsen immer weiter. Was sollte ich zuerst tun?
Der erste Schritt ist, den Zielprozess in VMMap zu öffnen und zu sehen, welche Kategorie wächst. Wächst Heap, ist ein natives Leck über malloc/new/HeapAlloc der Hauptverdächtige, und Geräte-SDKs oder C++/CLI- und Interop-Code werden zu den üblichen Übeltätern. Wächst Managed Heap, handelt es sich um ein Problem des verwalteten .NET-Heaps, sodass Sie mit der Untersuchung von Referenzen fortfahren, die der GC nicht freigeben kann (nie abgemeldete Ereignishandler und Ähnliches). Wächst Private Data (direkte Zuweisung über VirtualAlloc), ist Code oder ein SDK verdächtig, das große Blöcke wie Bildpuffer zuweist. Ist die Eingrenzung erfolgt, hält der Wechsel zum jeweils passenden Spezialwerkzeug (WinDbg, PerfView usw.) die Untersuchung auf Kurs.
Auf einem Offline-Geräte-PC sind die Stacks im Tab Threads nur eine Liste von Adressen und unlesbar. Was kann ich tun?
Das liegt daran, dass Symbole (PDBs) nicht heruntergeladen werden können, und Sie haben zwei Optionen: die Symbole mitbringen oder einen Dump mit zurücknehmen. Um sie mitzubringen, lassen Sie einen Entwicklungsrechner mit Internetzugang einmal Symbole gegen denselben OS-Build und dieselbe Anwendungskonfiguration auflösen, kopieren den gesamten lokalen Cache-Ordner (etwa C:\Symbols) auf den Geräte-PC und richten den Symbolpfad ausschließlich auf diesen lokalen Ordner. Um einen mitzunehmen, ist es zuverlässiger, während des Hängens einen Dump aufzuzeichnen und ihn in WinDbg auf einem Entwicklungsrechner zu analysieren, und das ist auch der bessere Weg, wenn Sie die Stacks einer verwalteten Anwendung genau lesen möchten. All das setzt voraus, dass Sie die PDBs Ihrer eigenen Anwendung für jeden Build archiviert haben.
Ist es problematisch, Process Explorer oder VMMap auf einem Produktiv- oder Geräte-PC zu installieren?
Beides sind eigenständige ausführbare Dateien, die keine Installation benötigen und ohne Registrierungseinträge oder residente Dienste laufen, sodass die Hürde, sie mitzubringen, niedrig ist. Sie müssen beim ersten Start die EULA akzeptieren, und wenn Sie sie aus einem Skript heraus steuern, können Sie diese mit dem Schalter /accepteula ausdrücklich akzeptieren. Ist das Netzwerk verfügbar, können Sie sie über Sysinternals Live (https://live.sysinternals.com) auch direkt ausführen, ohne etwas herunterzuladen. Aber während das Beobachten risikoarm ist, führen „eingreifende“ Vorgänge wie das Beenden oder Anhalten eines Prozesses, das Beenden eines Threads oder das erzwungene Schließen eines Handles direkt zu Unfällen — bleiben Sie im Produktivbetrieb beim Beobachten und Aufzeichnen und führen Sie es über Ihren normalen Änderungsfreigabeprozess durch.

Autorenprofil

Profilseite des Artikelautors.

Go Komura

Geschäftsführer von KomuraSoft LLC

Spezialisiert auf Windows-Softwareentwicklung, technische Beratung und Fehleranalyse, insbesondere bei bestehenden Systemen und schwer reproduzierbaren Störungen.

Zurück zum Blog