Diablo IV-Entwicklung bei Blizzard und Debuggen von Linux-Speicherabbildern in Visual Studio

Der Microsoft-Blog enthielt kürzlich einen Artikel von Bill Randolph, Blizzard Senior Software Engineer, der an Diablo IV arbeitet. Dieser Artikel behandelt einige Besonderheiten der Arbeit an Diablo IV und beschreibt insbesondere die Verwendung von Visual Studio zum Debuggen von Linux-basiertem Code. Heute machen wir Sie auf eine Übersetzung dieses Materials aufmerksam.





Einführung



Wenn wir an Diablo IV arbeiten, schreiben wir den gesamten Code unter Windows und kompilieren ihn dann für verschiedene Plattformen. Dies gilt auch für unsere Server, auf denen Linux ausgeführt wird. (Der Code enthält Anweisungen zur bedingten Kompilierung und gegebenenfalls Fragmente, die speziell für eine bestimmte Plattform geschrieben wurden.) Unsere Arbeit ist aus vielen Gründen so organisiert. Für den Anfang sind Windows die wichtigsten beruflichen Fähigkeiten unseres Teams. Selbst unsere Serverprogrammierer sind mit der Windows-Entwicklung bestens vertraut. Wir schätzen die Fähigkeit aller Programmierer in unserem Team, dieselben Tools und dieselbe Wissensbasis zu verwenden.



Ein weiterer wichtiger Grund für die Entwicklung unter Windows ist die Möglichkeit, die hochfunktionalen und zuverlässigen Tools von Visual Studio zu nutzen. Und selbst wenn wir etwas unter Linux entwickelt haben, kann ich sagen, dass es in der Linux-Welt nichts gibt, was mit Visual Studio verglichen werden kann.



Aus diesem Grund treten einige Schwierigkeiten auf, die auftreten, wenn der Server abstürzt und wir einen Speicherauszug debuggen müssen. Wir haben die Möglichkeit, uns remote bei einer virtuellen Maschine (oder genauer bei einem Container) anzumelden, bei der ein Fehler aufgetreten ist. Wir können gdb ausführen, um die Gründe für das Geschehene herauszufinden. Dieser Ansatz hat jedoch viele Nachteile. Beispiel: Wir stellen keine Binärdateien zusammen mit dem Quellcode bereit. Daher ist der Quellcode bei der Arbeit mit einer virtuellen Maschine oder einem Container in der GDB-Sitzung nicht verfügbar.



Eine weitere Komplikation liegt in der GDB selbst. Tatsache ist, dass wenn wir dieses Tool nicht regelmäßig verwenden, es nicht auf einem Niveau beherrscht werden kann, das zu uns passt. Einfach ausgedrückt, unsere Entwickler wären viel eher bereit, vertraute Tools zum Debuggen von Code zu verwenden. Da nur 2-3 unserer Entwickler gdb sehr gut kennen, sind sie diejenigen, die nach dem Problem suchen, wenn etwas schief geht. Dies kann nicht als optimale Verteilung der Arbeitslast für Programmierer bezeichnet werden.



Wir wollten schon immer einen Weg finden, um intuitiven Linux-Code zu debuggen. Aus diesem Grund freuen wir uns sehr, die neue Visual Studio-Funktion verwenden zu können, mit der wir genau dieses Problem in einer vertrauten Umgebung lösen können! Und es wäre keine Übertreibung zu sagen, dass unser Traum dadurch wahr geworden ist.





Über unseren Code-Debugging-Prozess



Das Debuggen von Linux-Code in Visual Studio ist nur möglich, wenn das Windows-Subsystem für Linux (WSL) auf dem System installiert ist oder wenn die Verbindung zu Linux im Verbindungsmanager konfiguriert ist . Alle unsere Backend-Entwickler haben WSL mithilfe der Distribution installiert, auf der wir unser Projekt bereitstellen. Wir führen ein Skript aus, das ich geschrieben habe und das alle Entwicklungstools und Unterstützungsbibliotheken installiert, die zum Erstellen unseres Servers in WSL erforderlich sind.



(Ich werde kurz von unserem Hauptthema abweichen. Ich möchte betonen, dass wir zu dem Schluss gekommen sind, dass WSL die beste existierende Umgebung ist, in der Entwickler Änderungen in Linux-Builds testen können. Dieses Arbeitsschema sieht äußerst praktisch aus: Wechseln Sie zu WSL, indem Sie den Befehl verwenden cd



, um in ein freigegebenes Codeverzeichnis zu wechseln und das Projekt direkt von dort aus zu erstellen. Dies ist eine viel bessere Lösung als die Verwendung einer virtuellen Maschine oder sogar eines Containers. Wenn Sie Projekte mit CMake erstellen, können Sie auch verwenden die integrierte Visual Studio- Unterstützung für WSL .)



Ich werde Ihnen ein wenig über unsere Versammlungen erzählen. Wir entwickeln den Code unter Windows und haben eine Windows-Version unseres Servers, die für dieses Betriebssystem entwickelt wurde. Dies ist nützlich für uns, wenn wir an den üblichen Projektfunktionen arbeiten. Wir stellen unseren serverseitigen Code jedoch unter Linux bereit, was Builds unter Linux erfordert. Linux-Assemblys werden in einer Buildfarm erstellt. Es verwendet ein Build-System, das auf einem Linux-Computer ausgeführt wird. Mit seiner Hilfe werden unser Serverprojekt und der entsprechende Container zusammengestellt, der später bereitgestellt wird. Linux-Binärdateien werden nur in Containern bereitgestellt. Normalerweise haben Entwickler keinen Zugriff auf diese Container.



Wenn einer der Server in unserer Infrastruktur ausfällt, werden wir durch ein spezielles Skript darüber informiert. Anschließend werden die Speicherauszugsdateien in einen freigegebenen Netzwerkordner geschrieben. Zum Debuggen dieser Dateien unter Linux oder Visual Studio benötigen Sie ein Arbeitsprogramm. Beim Debuggen ist es hilfreich, genau dieselben gemeinsam genutzten Bibliotheken zu verwenden, die im bereitgestellten Container verwendet werden. Wir verwenden ein anderes Skript, um diese Dateien abzurufen. Zuerst kopieren wir den Speicherauszug auf den lokalen Computer, führen dann das Skript aus und übergeben ihm Informationen zu diesem Speicherauszug. Das Skript lädt den Docker-Container herunter, der für die getestete Version des Codes erstellt wurde, extrahiert daraus die ausführbaren Dateien unseres Servers sowie bestimmte gängige Laufzeitbibliotheken. All dies wird für gdb benötigt. (Dies vermeidet bei der Arbeit mit gdb die Kompatibilitätsprobleme, die auftreten können, wennWenn die WSL-Version des Systems nicht genau mit der bereitgestellten Linux-Version übereinstimmt.) Das Skript, das eine Debugging-Sitzung einrichtet, schreibt Daten in ~/.gdbinit



Dies zeigt an, dass gemeinsam genutzte Bibliotheken Systembibliotheken sind.



Dann gehen wir zu Visual Studio, wo der Spaß beginnt. Wir laden eine Build-Lösung für die Windows-Version unserer Server herunter. Dann öffnen wir mit dem Befehl einen neuen Debug-Dialog Debug -> Other Debug Targets -> Debug Linux Core Dump with Native Only



. Wir aktivieren das Kontrollkästchen Debug on WSL



und geben die Pfade zu den Dump-Dateien und den Server-Binärdateien ein (für WSL bestimmt!). Drücken Sie danach einfach die Taste Debug



und beobachten Sie, was passiert.





Starten des Debuggens in Visual Studio



Visual Studio startet gdb automatisch in der WSL. Nachdem das System einige Zeit mit der Festplatte gearbeitet hat, wird der Aufrufstapel des fehlgeschlagenen Programms angezeigt und der Anweisungszeiger auf die entsprechende Codezeile gesetzt. Dies ist wirklich eine schöne neue Welt!



Als nächstes beschäftigen wir uns mit der Identifizierung des Fehlers selbst. Wir haben einen Fehlerbehandler, der das entsprechende Ereignis abfängt, um einige Serviceprozeduren auszuführen. Daher befinden sich Informationen zum Fehler selbst auf einem Single-Threaded-Server tiefer im Aufrufstapel. Einige unserer Server sind jedoch Multithread-Server. Und der Absturz kann auf jedem ihrer Threads passieren. Der Fehlerbehandler protokolliert Informationen zum Code der fehlerhaften Datei und zur Zeilennummer. Die Untersuchung dieser Daten gibt uns daher den ersten Hinweis. Wir suchen den Platz im Aufrufstapel, der der Ausführung dieses Codes entspricht.



Früher, vor einigen Wochen, hätten wir gdb verwendet, um alle Threads zurückzuverfolgen, und dann die resultierende Liste gescannt, um den Thread zu finden, dessen Aufrufstapel höchstwahrscheinlich abgestürzt ist. Wenn sich der Thread beispielsweise in einem Ruhezustand befand, stürzte er höchstwahrscheinlich nicht ab. Wir brauchen einen Stapel mit mehr als ein paar Frames und Informationen, die wir mit einem schlafenden Thread zu tun haben. Als nächstes müssen wir den Code untersuchen, um zu verstehen, wo das Problem liegt. Wenn es etwas Einfaches ist, können Sie es direkt im Code sehen. Wenn wir vor einem komplizierteren Problem stehen, müssen wir auf die Fähigkeiten von gdb zurückgreifen, um den Status des Prozesses zu untersuchen.



Aber Visual Studio bietet uns viel leistungsfähigere Funktionen als zuvor. In Multithread-Umgebungen können Sie in einer Debug-Sitzung ein Fenster öffnen Threads



und auf die Threads klicken, um deren Stapel anzuzeigen. Dies ist jedoch dem in gdb verwendeten Ansatz sehr ähnlich. Wenn Sie beispielsweise 50 Themen studieren müssen, kann dies zu einer ziemlich zeitaufwändigen und langweiligen Aufgabe werden. Glücklicherweise verfügt Visual Studio über ein Tool, das diese Aufgabe erheblich vereinfacht. Dies ist das Fenster " Parallele Stapel" .



Ich gebe zu, die meisten von uns wussten nichts über Parallel Stacks, bis Erica Sweet und ihr Team uns davon erzählten. Wenn während der Debug-Sitzung der Befehl ausgeführt wird Debug -> Windows -> Parallel Stacks



- Ein neues Fenster wird geöffnet, in dem Informationen zum Aufrufstapel jedes Threads im untersuchten Prozess angezeigt werden. Dies ist so etwas wie eine Vogelperspektive des gesamten Prozessraums. Jeder Stapelrahmen eines Threads kann doppelt angeklickt werden. Danach springt Visual Studio sowohl im Quellcodefenster als auch im Aufrufstapelfenster zu diesem Frame. Dies hilft uns sehr, Zeit zu sparen.



Sobald wir den Code in der Nähe der Absturzstelle sehen, können wir die Variablen mit der Maus, mit QuickWatch oder mit einem der vielen Visual Studio-Tools untersuchen. Natürlich werden in Release-Builds viele Variablen optimiert, viele jedoch nicht! Mithilfe der Visual Studio-Oberfläche können wir das Problem viel schneller als zuvor mit gdb lokalisieren.







Ergebnis



Unser Team ist einfach froh, Linux-Dumps in Visual Studio, der Umgebung, in der wir entwickeln, debuggen zu können. Für uns ist dies eine wesentliche Verbesserung, da viel mehr Entwickler als je zuvor Probleme in freier Wildbahn diagnostizieren können. Auf diese Weise können wir alle die leistungsstarken Debugging-Tools von Visual Studio nutzen. Nachdem die vorläufige Vorbereitung der Arbeitsumgebung abgeschlossen ist, können Sie in wenigen Minuten an einer Visual Studio-Debug-Sitzung teilnehmen. Diese Funktion erhöht die Geschwindigkeit beim Auffinden von Problemen und die Effizienz unserer Arbeit erheblich. Vielen Dank an Erica und ihr Team für ihre Hilfe.



Was ist für Sie in Visual Studio am nützlichsten?






All Articles