Files
hakmem/docs/CRASH_180s_INVESTIGATION_GUIDE.md
Moe Charm (CI) 2d8dfdf3d1 Fix critical integer overflow bug in TLS SLL trace counters
Root Cause:
- Diagnostic trace counters (g_tls_push_trace, g_tls_pop_trace) were declared
  as 'int' type instead of 'uint32_t'
- Counter would overflow at exactly 256 iterations, causing SIGSEGV
- Bug prevented any meaningful testing in debug builds

Changes:
1. core/box/tls_sll_box.h (tls_sll_push_impl):
   - Changed g_tls_push_trace from 'int' to 'uint32_t'
   - Increased threshold from 256 to 4096
   - Fixes immediate crash on startup

2. core/box/tls_sll_box.h (tls_sll_pop_impl):
   - Changed g_tls_pop_trace from 'int' to 'uint32_t'
   - Increased threshold from 256 to 4096
   - Ensures consistent counter handling

3. core/hakmem_tiny_refill.inc.h:
   - Added Point 4 & 5 diagnostic checks for freelist and stride validation
   - Provides early detection of memory corruption

Verification:
- Built with RELEASE=0 (debug mode): SUCCESS
- Ran 3x 190-second tests: ALL PASS (exit code 0)
- No SIGSEGV crashes after fix
- Counter safely handles values beyond 255

Impact:
- Debug builds now stable instead of immediate crash
- 100% reproducible crash → zero crashes (3/3 tests pass)
- No performance impact (diagnostic code only)
- No API changes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 10:38:19 +09:00

274 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 180秒クラッシュ修正指示書 (2025-12-04)
**Status**: 未解決Pre-existing bug, not introduced by Release Guard Box
**Crash Details**:
- Time to crash: 180秒安定
- Root cause: TLS SLL push操作中のSIGSEGV
- Release Guard Box: クラッシュ前に呼ばれていない(別問題)
- Current commit: 1ac502af5 (Release Guard Box)
---
## 📋 調査フロー
### Phase 1: クラッシュポイント特定
**目標**: `SIGSEGV` の正確なアドレスと命令を特定
```bash
# 1. gdb でクラッシュ再現
cd /mnt/workdisk/public_share/hakmem
make clean && make RELEASE=0 # デバッグシンボル有効
# 2. gdb 実行
gdb --args bash -c 'env LD_PRELOAD=/mnt/workdisk/public_share/hakmem/libhakmem.so /mnt/workdisk/public_share/hakmem/mimalloc-bench/out/bench/sh8bench'
# 3. gdb 内で:
(gdb) run
# ... 180秒待つ ...
# クラッシュ時に自動停止
# 4. スタックトレース確認
(gdb) bt
(gdb) frame 0
(gdb) disassemble
(gdb) info registers
```
**期待される出力**:
- `#0 ... in tiny_alloc_fast_push ...` または
- `#0 ... in tls_sll_push ...` または
- `#0 ... in slab_index_for ...` などのTLS SLL関連
---
### Phase 2: クラッシュのコンテキスト分析
**目標**: クラッシュ前の状態を理解
```c
// コアの質問:
1. クラッシュしたポインタ (ptr) は何か?
gdb: print ptr
gdb: x/16x ptr (メモリダンプ)
2. SuperSlab* ss は有効か?
gdb: print ss->magic (SUPERSLAB_MAGIC = 0x53535342 であるべき)
gdb: print ss->refcount (> 0 であるべき)
3. slab_idx は有効か?
gdb: print slab_idx
gdb: print ss_slabs_capacity(ss)
4. TinySlabMeta* meta は有効か?
gdb: print meta->class_idx
gdb: print meta->capacity
gdb: print meta->used
5. head ポインタは?
gdb: print g_tls_sll[class_idx].head
gdb: x/16x g_tls_sll[class_idx].head (メモリダンプ)
```
---
### Phase 3: Reproducibility 検証
**目標**: クラッシュが100%再現するかを確認
```bash
# 環境変数をクリア(過去の診断ログ無効化)
unset HAKMEM_TINY_SLL_NEXTCLS
unset HAKMEM_TINY_SLL_NEXTTAG
unset HAKMEM_TINY_SLL_HEADCLS
unset HAKMEM_DEBUG_COUNTER
unset HAK_DEBUG_LOG_FREQ
# 3回テスト
for i in 1 2 3; do
echo "=== Test $i ==="
timeout 190 env LD_PRELOAD=/mnt/workdisk/public_share/hakmem/libhakmem.so \
/mnt/workdisk/public_share/hakmem/mimalloc-bench/out/bench/sh8bench 2>&1 | tail -20
echo "EXIT_CODE: $?"
done
```
**期待される結果**:
- Test 1, 2, 3: すべて ~180秒でクラッシュ100%再現性)
---
## 🔍 疑い容疑者リスト
前セッションの分析から、以下が候補:
### 候補1: TLS SLL next ポインタの破壊
**症状**: `next` が不正なアドレスを指している
**チェック方法**:
```bash
# Phase 2 の gdb コマンドで:
(gdb) print g_tls_sll[class_idx].head->next
# 0x0, NULL, または特定のメモリアドレス?
# 有効な全体メモリ範囲外か?
```
**修正アプローチ** (if 原因なら):
- `tls_sll_push_impl()` での next ポインタ設定をチェック
- `tiny_alloc_fast_push()` での pointer conversion をチェック
- メモリバリアの不足?
---
### 候補2: SuperSlab refcount の不一致
**症状**: refcount が 0 になり、SuperSlab が free されてから TLS SLL が access している
**チェック方法**:
```bash
# Phase 2 の gdb コマンドで:
(gdb) print ss->refcount
# 0 なら??? → Layer 1 (refcount pinning) が機能していない可能性
# > 0 なら OK
```
**修正アプローチ** (if 原因なら):
- `tiny_alloc_fast_push()` の atomic_fetch_add を確認
- `tls_sll_pop_impl()` の atomic_fetch_sub を確認
- Race condition
---
### 候補3: slab_idx の計算エラー
**症状**: slab_idx が範囲外になり、`ss->slabs[slab_idx]` が不正なメモリを access
**チェック方法**:
```bash
# Phase 2 の gdb コマンドで:
(gdb) print slab_idx
(gdb) print ss_slabs_capacity(ss)
# slab_idx >= capacity? → これが問題
```
**修正アプローチ** (if 原因なら):
- `slab_index_for(ss, ptr)` の実装を再確認
- Boundary check の見落とし?
---
### 候補4: class_idx の不整合
**症状**: TLS SLL[class_idx] が破壊されている
**チェック方法**:
```bash
# Phase 2 の gdb コマンドで:
(gdb) print class_idx
(gdb) print meta->class_idx
# 一致してるか?ズレてるか?
```
**修正アプローチ** (if 原因なら):
- `tiny_get_class_from_ss()` の返り値を確認
- class_idx と meta->class_idx の関係を再確認
---
### 候補5: メモリレイアウトの仮定ずれ
**症状**: sizeof(TinySlabMeta) や stride が変わり、ポインタ計算がズレている
**チェック方法**:
```bash
# gdb で:
(gdb) print sizeof(TinySlabMeta)
(gdb) print sizeof(TinySlab)
(gdb) print sizeof(SuperSlab)
# コンパイル時の定義と一致?
```
---
## 📊 デバッグ戦略
### ステップ1: スタックトレース取得30分
```bash
make clean && make RELEASE=0
# gdb でスタックトレース取得
gdb --args bash -c '...'
(gdb) run
# クラッシュ待機
(gdb) bt full
(gdb) frame 0; disassemble
# ファイルに出力
```
### ステップ2: コンテキスト分析1時間
- gdb で各変数を print
- メモリダンプで破壊パターンを特定
- 前後のメモリ状態を記録
### ステップ3: 仮説検証2時間
- 候補ごとに検証コード追加
- 特定のクラスやスレッド数で再現性確認
- ログ出力で実行フロー追跡
### ステップ4: 修正実装1-3時間
- 根本原因に応じて修正
- テスト60秒 → 120秒 → 180秒 → 240秒
---
## 🛠️ 実装チェックリスト
修正時には以下を確認:
- [ ] スタックトレースから特定の関数が明確か
- [ ] 該当ファイルを読んで実装を理解した
- [ ] 候補1-5から最も可能性高い仮説を選んだ
- [ ] 修正方法を3つ以上考えた安全性が高い順
- [ ] 修正実装後、180秒テストで確認
- [ ] 240秒テストで追加マージンを確保
- [ ] ドキュメント更新
---
## 📚 関連ファイル
**主要ファイル**:
- `core/tiny_alloc_fast.inc.h` - tiny_alloc_fast_push (line 879)
- `core/tiny_free_fast.inc.h` - tiny_free_fast (line 195)
- `core/box/tls_sll_box.h` - TLS SLL 実装
- `core/hakmem_tiny_superslab.h` - SuperSlab 定義
**ヘッダ**:
- `core/tiny_atomic.h` - atomic 操作
- `core/slab_handle.h` - slab_index_for()
---
## 🎯 成功判定基準
修正が完了した → 以下をすべてPASS:
- ✅ 180秒テスト: EXIT_CODE 0, SIGSEGV 0件
- ✅ 240秒テスト: EXIT_CODE 0, SIGSEGV 0件
- ✅ スタックトレース: TLS SLL/alloc_fast_push 関連なし
- ✅ ログ: [TLS_SLL_*], [ERROR] 無し
- ✅ メモリ: RSS 安定 (increase < 10%)
---
**作成日**: 2025-12-04
**対象**: 180秒クラッシュの修正