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

Metin2 Core Crash Fix: Reading Core Dumps Step by Step

If you run a Metin2 server, sooner or later you will hit a metin2 core crash: the game core (the game process) suddenly dies, players drop their connections, and a core dump file is left behind. Most people panic at this point, restart the process and ignore the problem. But that core dump is the single most valuable source you have — it describes the exact cause of the crash, line by line. In this guide I will show you step by step how to read a core dump with gdb, how to interpret the backtrace, and how to permanently fix the most common crash causes.

What is a core dump and why does it matter?

When a process receives a fatal signal (usually SIGSEGV — an invalid memory access), the operating system can write the current memory image of the process to disk. This is called a core dump. On FreeBSD the file is usually named game.core; on Linux it is core or core.PID, created in the process's working directory. It contains the call stack, register values and the last state of the variables. In other words, it freezes the moment of the crash like a photograph.

One important point: core dump generation has to be enabled, otherwise you have nothing to analyse.

# Show the current limit
ulimit -c
# Allow unlimited core dumps (before you start game)
ulimit -c unlimited

On Linux, core_pattern controls where the core file is written and under what name. Make sure the kernel does not redirect the core somewhere else (e.g. systemd-coredump):

cat /proc/sys/kernel/core_pattern
# For a simple PID-named file in the working directory:
echo 'core.%p' > /proc/sys/kernel/core_pattern

Opening the core dump with gdb

The heart of the analysis is gdb. To see the cause of the crash you must open the core file together with the exact same game binary that produced it; if you open it with a different build the addresses won't line up and the backtrace will be meaningless.

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

Once gdb is open, your first command should be bt (backtrace). It lists the call chain at the moment of the crash, from the innermost function outward:

(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 the example above, this=0x0 is the critical clue: GetLevel() was called on a null pointer. For more context these commands do the job:

  • bt full — also shows the local variables in each stack frame.
  • thread apply all bt — dumps the stacks of every thread for multi-threaded crashes.
  • frame 1 followed by print *this — lets you inspect the variables of a specific frame.
  • info registers — shows the register state.

You can't read a backtrace without debug symbols

If your bt output shows ?? () and only addresses instead of function names, your binary has been stripped — the symbols have been removed. In that case there is little you can do. The fix is to compile the source with the -g flag and keep the symbols.

# Add to your Makefile / build flags
CFLAGS += -g
# Do NOT strip the build before deploying; keep a separate debug copy

A good habit: keep a separate, non-stripped copy of the live binary compiled with -g. When a core drops, open it with that copy. Even if you run a separate, stripped build in production for performance, the addresses will match as long as it is the same compilation.

Common crash causes

Over the years these are the most frequent metin2 core crash causes I have seen in Metin2 source code:

  • Null or freed CHARACTER pointer: if a quest timer, party or p2p message still references a player after they have logged out, access through the invalid pointer leads to a crash. A this=0x0 or a strange address in the backtrace is the sign.
  • Corrupt proto data: accessing a non-existent vnum in item_proto, mob_proto or quests. A missing item/mob definition crashes through an out-of-bounds access.
  • Quest errors: a logic mistake on the Lua side passes an invalid argument to a native function. The SYSERR lines just before the crash in syserr.txt usually name the quest.
  • Packet/buffer overflow: an incorrectly sized packet struct or untrusted client input causes an out-of-bounds read/write.
  • Double free: the same object is deleted twice; especially common in event/timer cancellations.

Once the backtrace leads you to a file and line, adding a guard that checks the validity of the pointer on that line is often the fastest lasting fix:

// Before: crashes if ch is null
ch->ComputePoints();

// After: defensive check
if (ch == NULL)
    return;
ch->ComputePoints();

Read the logs alongside the core

A core dump is not alone. The syserr.txt and syslog.txt files in the game process's working directory keep the last events before the crash with timestamps. A practical method: take the timestamp of the crash and search for that second in syserr.txt.

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

Often the backtrace tells you "where" it crashed, while syserr.txt tells you "after which event" it crashed. Combine the two and the "why" emerges.

Reproduce and verify the crash

After making a fix, always try to trigger the crash again: which item, which quest, which NPC interaction was crashing it? Repeat the steps on a test server. You have only verified the fix when the crash can no longer be reproduced. Otherwise you may have merely suppressed the symptom and missed the root cause.

Frequently Asked Questions

No core dump file is being created — why?

The most common reason is that ulimit -c is 0; set ulimit -c unlimited in the shell that starts game. On Linux also check that core_pattern isn't redirecting the core to systemd-coredump and that the directory is writable.

The backtrace has no function names, only addresses. What do I do?

It means your binary is stripped. Recompile the source with the -g flag, keep the symbols, and open the core with that symbol-rich copy. You can't extract a meaningful stack from a stripped binary.

The crash is random with no fixed steps — how do I catch it?

Collect several core dumps and compare all their backtraces. If the same function or line repeats, that is the root cause. For non-repeating cases that point to memory corruption, running a test build under valgrind or AddressSanitizer gives you clues.

If your server won't stay stable, I can help you analyse the core dumps and fix recurring crashes at the source level. Get in touch with me for Metin2 game core debugging and server stability — contact me.

Bu kategorideki tüm yazılar →

Devamı için