プロジェクト

全般

プロフィール

バグ #479

完了

バグ #474: コードベース健全性: メモリリーク・重大バグの一括調査と修正

並行処理レース・無制限キャッシュの是正

バグ #479: 並行処理レース・無制限キャッシュの是正

エージェント ちゃん さんが7日前に追加. 6日前に更新.

ステータス:
完了
優先度:
通常
担当者:
対象バージョン:
開始日:
2026/06/29
期日:
進捗率:

100%

予定工数:

説明

現象

複数スレッドが同期なしで共有可変状態にアクセスし、可視性不足・レース・CME・スレッド未終了の温床がある。再現条件が状況依存なため、実装着手時に各項を再検証する。

対象箇所

  1. AbstractAudioDriver 並列ロード src/bms/player/beatoraja/audio/AbstractAudioDriver.java:410
    • BoundedParallelExecutor(:440)の並列ロードで localSlice[note.getWav()] への check-then-create レース + 非スレッドセーフな libgdx Array.add。タスクキー(wavid)とスライス処理キー(note.getWav())が別 ID になり得るため同一要素を複数スレッドが触る。スライス音源欠落/AIOOBE の温床。
  2. AbstractResult/MusicResult の非 volatile 共有 src/bms/player/beatoraja/result/AbstractResult.java:20,35,39 / MusicResult.java
    • IR 送信ワーカースレッド(startVirtual("beatoraja-ir-music-result", ...))が非 volatile な state/ranking/rankingOffset を書き、描画スレッドが同期なしで読む。IR 結果が描画に反映されない/古い state のまま遷移等。
  3. PortAudioDriver src/bms/player/beatoraja/audio/PortAudioDriver.java:29,193,246-249
    • ミキサー停止フラグ stop が非 volatile(スレッド未終了でスレッド+オーディオストリームリークの恐れ)。:249 は最大 1 秒の CPU スピンウェイト。
  4. BitmapFontCache src/bms/player/beatoraja/skin/BitmapFontCache.java:11
    • static HashMap が無制限増加・エビクションなし、かつスキン読込スレッドと描画スレッドから並行アクセスで CME/破損リスク。

参考:StreamController の busy-wait src/bms/player/beatoraja/stream/StreamController.java:70

  • while (!pipeBuffer.ready()); で CPU 1 コアをスピン消費(資源浪費、機能バグではない)。

修正方針

  • stop/state の volatile 化。localSlice への並列アクセスを同期 or per-key ロック化。BitmapFontCacheConcurrentHashMap + 上限/解放に。ranking の差し替え/更新はロック。スピンウェイトは適切な待機に置換。
  • 影響範囲が広いため、必要に応じて個別チケットに分割して慎重に対応。

検証

  • 並列ロードを繰り返してもスライス音源欠落/AIOOBE が出ない。
  • IR 結果がリザルトに反映される。
  • 終了時にオーディオスレッドが確実に停止する。

他の形式にエクスポート: PDF Atom