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

Metin2 Core Crash Oplossen: Core Dumps Lezen met GDB

Als je een Metin2-server beheert, loop je vroeg of laat tegen een metin2 core crash aan: de game core (het game-proces) valt plotseling stil, spelers verliezen hun verbinding en er blijft een core dump-bestand achter. De meeste mensen raken op dat moment in paniek, herstarten het proces en negeren het probleem. Maar die core dump is de waardevolste bron die je hebt: hij beschrijft de exacte oorzaak van de crash, regel voor regel. In deze gids laat ik je stap voor stap zien hoe je een core dump leest met gdb, hoe je de backtrace interpreteert en hoe je de meest voorkomende crashoorzaken blijvend oplost.

Wat is een core dump en waarom is hij belangrijk?

Wanneer een proces een fataal signaal ontvangt (meestal SIGSEGV — een ongeldige geheugentoegang), kan het besturingssysteem het huidige geheugenbeeld van het proces naar schijf schrijven. Dat heet een core dump. Op FreeBSD heet het bestand meestal game.core; op Linux is het core of core.PID, aangemaakt in de werkmap van het proces. Het bevat de call stack, de registerwaarden en de laatste toestand van de variabelen. Met andere woorden: het bevriest het moment van de crash als een foto.

Eén belangrijk punt: het genereren van core dumps moet ingeschakeld zijn, anders heb je niets om te analyseren.

# Toon de huidige limiet
ulimit -c
# Sta onbeperkte core dumps toe (voordat je game start)
ulimit -c unlimited

Op Linux bepaalt core_pattern waar het core-bestand wordt geschreven en onder welke naam. Zorg dat de kernel de core niet ergens anders heen stuurt (bijv. naar systemd-coredump):

cat /proc/sys/kernel/core_pattern
# Voor een eenvoudig bestand met PID in de werkmap:
echo 'core.%p' > /proc/sys/kernel/core_pattern

De core dump openen met gdb

Het hart van de analyse is gdb. Om de oorzaak van de crash te zien, moet je het core-bestand openen samen met precies dezelfde game-binary die hem heeft geproduceerd; open je hem met een andere build, dan kloppen de adressen niet en is de backtrace betekenisloos.

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

Zodra gdb open is, moet je eerste commando bt (backtrace) zijn. Het toont de keten van aanroepen op het moment van de crash, van de binnenste functie naar buiten toe:

(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  ...

In het voorbeeld hierboven is this=0x0 de cruciale aanwijzing: GetLevel() werd aangeroepen op een null pointer. Voor meer context doen deze commando's hun werk:

  • bt full — toont ook de lokale variabelen in elke stack frame.
  • thread apply all bt — dumpt de stacks van alle threads bij multithreaded crashes.
  • frame 1 gevolgd door print *this — laat je de variabelen van een specifieke frame inspecteren.
  • info registers — toont de toestand van de registers.

Zonder debugsymbolen lees je geen backtrace

Als je bt-uitvoer ?? () en alleen adressen toont in plaats van functienamen, is je binary gestript — de symbolen zijn verwijderd. In dat geval kun je weinig doen. De oplossing is de broncode te compileren met de -g-vlag en de symbolen te behouden.

# Voeg toe aan je Makefile / build-flags
CFLAGS += -g
# Strip de build NIET vóór het deployen; houd een aparte debug-kopie

Een goede gewoonte: bewaar een aparte, niet-gestripte kopie van de live binary, gecompileerd met -g. Wanneer er een core valt, open je hem met die kopie. Zelfs als je in productie om prestatieredenen een aparte, gestripte build draait, kloppen de adressen zolang het dezelfde compilatie is.

Veelvoorkomende crashoorzaken

In de loop der jaren zijn dit de meest voorkomende metin2 core crash-oorzaken die ik in Metin2-broncode ben tegengekomen:

  • Null- of vrijgegeven CHARACTER-pointer: als een questtimer, party of p2p-bericht nog naar een speler verwijst nadat die is uitgelogd, leidt toegang via de ongeldige pointer tot een crash. Een this=0x0 of een vreemd adres in de backtrace is het teken.
  • Corrupte proto-data: toegang tot een niet-bestaande vnum in item_proto, mob_proto of quests. Een ontbrekende item-/mob-definitie crasht via een out-of-bounds-toegang.
  • Questfouten: een logische fout aan de Lua-kant geeft een ongeldig argument door aan een native functie. De SYSERR-regels vlak voor de crash in syserr.txt noemen meestal de quest.
  • Packet-/bufferoverloop: een verkeerd gedimensioneerde packet-struct of niet-vertrouwde clientinvoer veroorzaakt een out-of-bounds lees-/schrijfbewerking.
  • Double free: hetzelfde object wordt twee keer met delete vrijgegeven; vooral gebruikelijk bij het annuleren van events/timers.

Zodra de backtrace je naar een bestand en regel heeft geleid, is een guard toevoegen die de geldigheid van de pointer op die regel controleert vaak de snelste blijvende oplossing:

// Voor: crasht als ch null is
ch->ComputePoints();

// Na: defensieve controle
if (ch == NULL)
    return;
ch->ComputePoints();

Lees de logs samen met de core

Een core dump staat niet alleen. De bestanden syserr.txt en syslog.txt in de werkmap van het game-proces bewaren de laatste gebeurtenissen vóór de crash, met tijdstempels. Een praktische methode: neem de tijdstempel van de crash en zoek die seconde op in syserr.txt.

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

Vaak vertelt de backtrace je "waar" het crashte, terwijl syserr.txt je vertelt "na welke gebeurtenis". Combineer de twee en het "waarom" komt naar boven.

De crash reproduceren en verifiëren

Probeer na een fix altijd de crash opnieuw uit te lokken: welk item, welke quest, welke NPC-interactie veroorzaakte hem? Herhaal de stappen op een testserver. Je hebt de fix pas geverifieerd wanneer de crash niet meer te reproduceren is. Anders heb je misschien alleen het symptoom onderdrukt en de onderliggende oorzaak gemist.

Veelgestelde vragen

Er wordt geen core dump-bestand aangemaakt — waarom?

De meest voorkomende reden is dat ulimit -c op 0 staat; stel ulimit -c unlimited in in de shell die game start. Controleer op Linux ook dat core_pattern de core niet omleidt naar systemd-coredump en dat de map schrijfbaar is.

De backtrace heeft geen functienamen, alleen adressen. Wat moet ik doen?

Dat betekent dat je binary gestript is. Hercompileer de broncode met de -g-vlag, behoud de symbolen en open de core met die symboolrijke kopie. Uit een gestripte binary haal je geen bruikbare stack.

De crash is willekeurig zonder vaste stappen — hoe vang ik hem?

Verzamel meerdere core dumps en vergelijk al hun backtraces. Als dezelfde functie of regel terugkeert, ligt daar de onderliggende oorzaak. Voor niet-terugkerende gevallen die op geheugencorruptie wijzen, geeft een testbuild draaien onder valgrind of AddressSanitizer aanwijzingen.

Als je server niet stabiel blijft, kan ik je helpen de core dumps te analyseren en terugkerende crashes op broncode-niveau op te lossen. Neem contact met me op voor Metin2 game core-debugging en serverstabiliteit — neem contact op.

Bu kategorideki tüm yazılar →

Devamı için