한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

ゲームラグ白書 › L9 サーバーのゲームプロセス

デッドロック Deadlock

原因ID sp-deadlock · 主担当 ゲーム開発チーム・サーバー開発

図と実験のあるメインページでこのカードを開く →

2つのスレッドが互いに相手の取ったロックを待つと、永遠に止まったままになります。

なぜ スレッドAはロック1を取ったままロック2を、Bはロック2を取ったままロック1を待つ → すると 両方とも永遠に止まり、関連するスレッドも次々に止まる → 画面では サーバー全体が停止し、ウォッチドッグによる再起動で全員が切断

症状
フリーズ, 切断
要因
ストール
誰に起きるか
サーバー全体, 特定の機能だけ
いつ
ときどきランダムに, 人が集中したとき
担当
主担当 ゲーム開発チーム・サーバー開発
ゲーム開発チームの対応
ロックを取る順序のルール、タイムアウト付きのロック、ウォッチドッグと停止した瞬間のスレッドダンプの記録。
グラフでは
接続が一斉に切れる · 接続数、サーバーの送信量
確認箇所
止まっている間に全スレッドのコールスタックを取得。JVMはjstack(デッドロックを自動で検出して表示)、.NETはdotnet-stack、ネイティブのサーバーはgdbのthread apply all bt、またはgcoreでコアファイルを取っておき、再起動した後で分析
該当する場合
2つ以上のスレッドが、互いに相手の取ったロックを待つスタックのまま止まっており、その間プロセスのCPU使用率が0に近い
該当しない場合
止まっている間にスレッド1つがCPUを100%使って回り続けていれば無限ループ。各スレッドがDB・外部の応答を待っていれば、同期呼び出しかスレッドプールの枯渇の側
確認手段
インフラのツールで確認(ゲームコード不要)

出典

  1. Runtime locking correctness validator Linux kernel
    2つのロックを互いに逆の順序で取ると循環待ちでデッドロック(lock inversion deadlock)、Linuxカーネルはロックの順序を検査して事前に警告
  2. Liveness, Readiness, and Startup Probes Kubernetes
    実行中なのに処理が進まないデッドロック状態をLiveness Probeで検知し、コンテナを再起動
  3. Diagnostic Tools (Java SE 21 Troubleshooting Guide) Oracle
    jstackは実行中のJVMの全スレッドのスタックを出力し、デッドロックも検出して表示(Found one Java-level deadlock)
  4. dotnet-stack diagnostic tool - .NET CLI Microsoft
    .NETプロセスの全スレッドのマネージドスタックをキャプチャして出力
  5. Threads (Debugging with GDB) GNU Project
    thread apply allで全スレッドに同じコマンド(bt:コールスタックの出力)を実行
  6. gcore(1) — Linux manual page gdb
    実行中のプログラムのコアファイルを作成し、作成後もプログラムはそのまま実行を続ける

あわせて読みたい原因

同じ層:L9 サーバーのゲームプロセス

同じ症状(フリーズ)を起こすほかの層の原因

図と実験のあるメインページでこのカードを見る