Warum würde es zu einem Stillstand kommen? (Windows)

8

Ich habe einen Prozess zur Überwachung von Verzeichnisänderungen, der Aktualisierungen von Dateien in einer Reihe von Verzeichnissen liest. Ich habe einen anderen Prozess, der kleine Schreiben zu vielen Dateien zu diesen Verzeichnissen durchführt (Testprogramm). Stellen Sie etwa 100 Verzeichnisse mit jeweils 10 Dateien und etwa 500 Dateien pro Sekunde dar.

Nach einer Weile läuft der Prozess des Verzeichnis-Monitors bei einem Aufruf von fclose() in einer Methode, die die Datei grundsätzlich abschließt. In dieser Methode, ich fopen() die Datei, überprüfen Sie, dass das Handle gültig ist, ein paar Suchvorgänge und liest, und rufen Sie dann fclose() . Diese Lesevorgänge werden alle von demselben Thread im Prozess ausgeführt. Nach dem Aufhängen geht der Thread nie weiter.

Ich konnte keine guten Informationen darüber finden, warum fclose() einen Deadlock auslösen könnte, anstatt irgendeine Art von Fehlercode zurückzugeben. Die Dokumentation erwähnt _fclose_nolock() , aber es scheint mir nicht verfügbar zu sein (Visual Studio 2003).

Der Hang tritt sowohl für Debug- als auch für Release-Builds auf. In einem Debug-Build kann ich sehen, dass fclose() Aufrufe _free_base() aufruft, die vor der Rückgabe hängen bleiben. Irgendeine Art von Aufruf in kernel32.dll = & gt; ntdll.dll = & gt; KernelBase.dll = & gt; ntdll.dll dreht sich. Hier ist die Assembly von ntdll.dll, die unendlich lange läuft:

%Vor%

Irgendwelche Ideen, was hier passiert?

    
Haw-Bin 23.05.2011, 17:19
quelle

2 Antworten

2

Ich habe dies als Kommentar gepostet, aber mir ist klar, dass das eine Antwort sein könnte ...

Aufgrund der Disassemblierung habe ich eine interne Heap-Struktur überschrieben, die von ntdll verwaltet wird, und es wird immer wieder eine Schleife durch eine verknüpfte Liste durchlaufen.

Insbesondere am Anfang der Schleife scheint der aktuelle Listenknoten in ebx zu stehen. Am Ende der Schleife, der erwartete letzte Knoten (oder Terminator, wenn Sie möchten - es sieht ein bisschen wie diese sind kreisförmige Listen und der letzte Knoten ist der gleiche wie der erste, Zeiger auf diesen Knoten bei [edi+4Ch] ) ist in eax enthalten. Wahrscheinlich ist das Ergebnis von cmp ebx, eax niemals gleich, weil es in der Liste einen Zyklus gibt, der durch eine Heap-Beschädigung eingeführt wurde.

Ich glaube nicht, dass das etwas mit Sperren zu tun hat, sonst würden wir einige atomare Anweisungen (zB lock cmpxchg , xchg , usw.) oder Aufrufe anderer Synchronisationsfunktionen sehen.

    
asveikau 31.05.2011, 23:21
quelle
0

Ich hatte einen ähnlichen Fall mit der Funktion zum Schließen von Dateien. In meinem Fall habe ich gelöst, indem ich die Close-Funktion anderen Funktionskörper eingebettet habe statt eigene Funktion zu haben.

Ich war auch misstrauisch (1) der Name der zu duplizierenden Datei (2) Windows-Planung (Datei-IO wurde nicht abgeschlossen, bevor die nächste Aufgabe gestartet wird. Windows-Planung und Multithreading ist hinter dem Vorhang, so ist es schwer zu überprüfen, aber ich habe ähnliches Problem, als ich versuchte, viele Daten in ASCII in der Schleife zu speichern. Speichern auf binär gelöst in diesem Fall.)

Meine Umgebung, IDE: Visual Studio 2015, Betriebssystem: Windows 7, Sprache: C ++

    
Cloud Cho 02.06.2017 23:02
quelle

Tags und Links