aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Metin2

Metin2 Core Crash beheben: Core Dumps richtig auslesen

Wenn du einen Metin2-Server betreibst, wirst du früher oder später auf einen metin2 core crash stoßen: Der Game Core (der game-Prozess) stirbt plötzlich, die Spieler verlieren ihre Verbindung und es bleibt eine Core-Dump-Datei zurück. Die meisten geraten an diesem Punkt in Panik, starten den Prozess neu und ignorieren das Problem. Doch dieser Core Dump ist die wertvollste Quelle, die du hast: Er beschreibt die genaue Ursache des Absturzes, Zeile für Zeile. In dieser Anleitung zeige ich dir Schritt für Schritt, wie du einen Core Dump mit gdb liest, wie du den Backtrace interpretierst und wie du die häufigsten Absturzursachen dauerhaft behebst.

Was ist ein Core Dump und warum ist er wichtig?

Wenn ein Prozess ein fatales Signal erhält (meist SIGSEGV — ein ungültiger Speicherzugriff), kann das Betriebssystem das aktuelle Speicherabbild des Prozesses auf die Festplatte schreiben. Das nennt man einen Core Dump. Unter FreeBSD heißt die Datei meist game.core; unter Linux ist es core oder core.PID, erstellt im Arbeitsverzeichnis des Prozesses. Sie enthält den Call Stack, die Registerwerte und den letzten Zustand der Variablen. Mit anderen Worten: Sie friert den Moment des Absturzes wie ein Foto ein.

Ein wichtiger Punkt: Die Erzeugung von Core Dumps muss aktiviert sein, sonst hast du nichts zum Analysieren.

# Aktuelles Limit anzeigen
ulimit -c
# Unbegrenzte Core Dumps erlauben (bevor du game startest)
ulimit -c unlimited

Unter Linux steuert core_pattern, wohin die Core-Datei geschrieben wird und unter welchem Namen. Stelle sicher, dass der Kernel den Core nicht woanders hinleitet (z. B. zu systemd-coredump):

cat /proc/sys/kernel/core_pattern
# Für eine einfache, PID-benannte Datei im Arbeitsverzeichnis:
echo 'core.%p' > /proc/sys/kernel/core_pattern

Den Core Dump mit gdb öffnen

Das Herzstück der Analyse ist gdb. Um die Ursache des Absturzes zu sehen, musst du die Core-Datei zusammen mit exakt derselben game-Binary öffnen, die sie erzeugt hat; öffnest du sie mit einem anderen Build, passen die Adressen nicht und der Backtrace ist sinnlos.

# FreeBSD
gdb ./game game.core
# Linux
gdb ./game core.12345

Sobald gdb geöffnet ist, sollte dein erster Befehl bt (Backtrace) sein. Er listet die Aufrufkette zum Zeitpunkt des Absturzes auf, von der innersten Funktion nach außen:

(gdb) bt
#0  0x081a2b3c in CHARACTER::GetLevel (this=0x0) at char.cpp:1042
#1  0x0819f0a1 in CHARACTER::ComputePoints (this=0x0) at char_battle.cpp:88
#2  ...

Im obigen Beispiel ist this=0x0 der entscheidende Hinweis: GetLevel() wurde auf einem Null-Pointer aufgerufen. Für mehr Kontext erledigen diese Befehle die Arbeit:

  • bt full — zeigt auch die lokalen Variablen in jedem Stack Frame.
  • thread apply all bt — gibt bei Multithread-Abstürzen die Stacks aller Threads aus.
  • frame 1 gefolgt von print *this — lässt dich die Variablen eines bestimmten Frames untersuchen.
  • info registers — zeigt den Zustand der Register.

Ohne Debug-Symbole liest sich kein Backtrace

Wenn deine bt-Ausgabe ?? () und nur Adressen statt Funktionsnamen zeigt, wurde deine Binary gestrippt — die Symbole wurden entfernt. In diesem Fall kannst du wenig tun. Die Lösung ist, die Quellen mit dem Flag -g zu kompilieren und die Symbole zu behalten.

# Zu deinem Makefile / deinen Build-Flags hinzufügen
CFLAGS += -g
# Den Build NICHT vor dem Deploy strippen; eine separate Debug-Kopie behalten

Eine gute Gewohnheit: Behalte eine separate, nicht gestrippte Kopie der Live-Binary, kompiliert mit -g. Wenn ein Core fällt, öffne ihn mit dieser Kopie. Selbst wenn du in der Produktion aus Performancegründen einen separaten, gestrippten Build betreibst, passen die Adressen, solange es dieselbe Kompilierung ist.

Häufige Absturzursachen

Über die Jahre sind dies die häufigsten metin2 core crash-Ursachen, die mir im Metin2-Quellcode begegnet sind:

  • Null- oder freigegebener CHARACTER-Pointer: Wenn ein Quest-Timer, eine Party oder eine p2p-Nachricht nach dem Logout noch auf einen Spieler verweist, führt der Zugriff über den ungültigen Pointer zum Absturz. Ein this=0x0 oder eine seltsame Adresse im Backtrace ist das Zeichen.
  • Beschädigte Proto-Daten: Zugriff auf eine nicht existierende vnum in item_proto, mob_proto oder Quests. Eine fehlende Item-/Mob-Definition stürzt durch einen Zugriff außerhalb der Grenzen ab.
  • Quest-Fehler: Ein Logikfehler auf der Lua-Seite übergibt einer nativen Funktion ein ungültiges Argument. Die SYSERR-Zeilen kurz vor dem Absturz in syserr.txt nennen meist die Quest.
  • Packet-/Buffer-Überlauf: Eine falsch dimensionierte Packet-Struct oder nicht vertrauenswürdige Client-Eingabe verursacht einen Lese-/Schreibzugriff außerhalb der Grenzen.
  • Double Free: Dasselbe Objekt wird zweimal mit delete freigegeben; besonders häufig beim Abbrechen von Events/Timern.

Sobald der Backtrace dich zu einer Datei und Zeile geführt hat, ist das Hinzufügen einer Prüfung, die die Gültigkeit des Pointers in dieser Zeile kontrolliert, oft die schnellste dauerhafte Lösung:

// Vorher: stürzt ab, wenn ch null ist
ch->ComputePoints();

// Nachher: defensive Prüfung
if (ch == NULL)
    return;
ch->ComputePoints();

Lies die Logs zusammen mit dem Core

Ein Core Dump steht nicht allein. Die Dateien syserr.txt und syslog.txt im Arbeitsverzeichnis des game-Prozesses bewahren die letzten Ereignisse vor dem Absturz mit Zeitstempeln auf. Eine praktische Methode: Nimm den Zeitstempel des Absturzes und suche diese Sekunde in syserr.txt.

tail -n 100 syserr.txt
grep -n "SYSERR" syserr.txt | tail -n 20

Oft sagt dir der Backtrace, "wo" es abgestürzt ist, während syserr.txt dir sagt, "nach welchem Ereignis". Kombiniere beides und das "Warum" tritt zutage.

Den Absturz reproduzieren und verifizieren

Versuche nach einem Fix immer, den Absturz erneut auszulösen: Welches Item, welche Quest, welche NPC-Interaktion hat ihn verursacht? Wiederhole die Schritte auf einem Testserver. Den Fix hast du erst dann verifiziert, wenn sich der Absturz nicht mehr reproduzieren lässt. Andernfalls hast du womöglich nur das Symptom unterdrückt und die eigentliche Ursache übersehen.

Häufige Fragen

Es wird keine Core-Dump-Datei erstellt — warum?

Der häufigste Grund ist, dass ulimit -c auf 0 steht; setze ulimit -c unlimited in der Shell, die game startet. Prüfe unter Linux außerdem, dass core_pattern den Core nicht zu systemd-coredump umleitet und dass das Verzeichnis beschreibbar ist.

Der Backtrace hat keine Funktionsnamen, nur Adressen. Was soll ich tun?

Das bedeutet, dass deine Binary gestrippt ist. Kompiliere die Quellen mit dem Flag -g neu, behalte die Symbole und öffne den Core mit dieser symbolreichen Kopie. Aus einer gestrippten Binary lässt sich kein brauchbarer Stack gewinnen.

Der Absturz ist zufällig ohne feste Schritte — wie fange ich ihn ein?

Sammle mehrere Core Dumps und vergleiche alle ihre Backtraces. Wenn sich dieselbe Funktion oder Zeile wiederholt, liegt dort die eigentliche Ursache. Für nicht wiederkehrende Fälle, die auf Speicherbeschädigung hindeuten, gibt ein Testbuild unter valgrind oder AddressSanitizer Hinweise.

Wenn dein Server nicht stabil bleibt, kann ich dir helfen, die Core Dumps zu analysieren und wiederkehrende Abstürze auf Quellcode-Ebene zu beheben. Melde dich für Metin2-Game-Core-Debugging und Serverstabilität — kontaktiere mich.

Bu kategorideki tüm yazılar →

Devamı için