Assessment of current approach: ✅ Stability achieved (no SIGSEGV) ❌ Symptoms proliferating ([TLS_SLL_NEXT_INVALID], [FREELIST_INVALID], etc.) ❌ Root causes remain untouched (multiple defensive layers accumulating) Warning Signs: - [TLS_SLL_NEXT_INVALID]: Freelist corruption happening frequently - refcount > 0 deferred releases: Memory accumulating - [NORMALIZE_USERPTR]: Pointer conversion bugs widespread Three Root Cause Hypotheses: A. Freelist next corruption (slab_idx calculation? bounds?) B. Pointer conversion inconsistency (user vs base mixing) C. SuperSlab reuse leaving garbage (lifecycle issue) Recommended Investigation Path: 1. Audit slab_index_for() calculation (potential off-by-one) 2. Add persistent prev/next validation to detect freelist corruption 3. Limit class 1 with forced base conversion (isolate userptr source) Key Insight: Current approach: Hide symptoms with layers of guards Better approach: Find and fix root cause (1-3 line fix expected) Risk Assessment: - Current: Stability OK, but memory safety uncertain - Long-term: Memory leak + efficiency degradation likely - Urgency: Move to root cause investigation NOW Timeline for root cause fix: - Task 1: slab_index_for audit (1-2h) - Task 2: freelist detection (1-2h) - Task 3: pointer audit (1h) - Final fix: (1-3 lines) Philosophy: Don't suppress symptoms forever. Find the disease. 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
9.0 KiB
9.0 KiB
📊 警告: 対処療法が増殖している (2025-12-03)
Status: 🟡 CAUTION - 症状を増やしてる可能性
Commit: 19ce4c1ac (refcount pinning)
Assessment: 多層防御は安定性を得たが、根本原因に蓋をしてる
🚨 問題認識
現在の状況
✅ sh8bench: 60秒完走(SIGSEGV ゼロ)
❌ しかし: [TLS_SLL_NEXT_INVALID] / [UNIFIED_FREELIST_INVALID] が多発
❌ つまり: 対処療法で「症状を見えなくしてる」だけ
対処療法の積み重ね
| 層 | 対策 | 内容 | 評価 |
|---|---|---|---|
| 1 | refcount pinning | SuperSlab 解放を遅延 | ⚠️ 治してない |
| 2 | release guards | refcount > 0 なら skip | ⚠️ 隠蔽 |
| 3 | next validation | 無効pointer を drop | ⚠️ リスト喪失 |
| 4 | freelist validation | 無効head を drop | ⚠️ メモリ喪失 |
| 5 | early decrement fix | refcount 過剰デクリメント削除 | ⚠️ 延期しただけ |
🔍 ログから見える本当の問題
パターン1: 無効なスラブインデックス
[TLS_SLL_NEXT_INVALID]
head slab_idx=56
→ next が slab_idx=0x45c相当(範囲外!)
解釈:
- next ポインタが「同一 SuperSlab 内」だが「範囲外」
- SuperSlab 内メモリが「スラブ単位で破壊」されてる
- または「スラブインデックス計算が間違ってる」
パターン2: 別スラブの混入
[UNIFIED_FREELIST_INVALID]
TLS スラブ(ss=0x…c00000, slab=3)のfreelist
→ ブロック pがss+0x1302(他スラブ相当)を指す
解釈:
- freelist の next が「別のスラブ」を指してる
- freelist が「スラブ境界を越えてリンク」されてる
- または「ポインタ計算が完全に狂ってる」
パターン3: userptr の混入
[TLS_SLL_NORMALIZE_USERPTR] 多数
解釈:
- userptr(offset +1 したもの)が TLS SLL に push されてる
- base pointer として expected なのに user pointer が来てる
- 型変換の誤り が多発
🎯 根本原因の仮説(修正版)
仮説A: Freelist 自体が破壊されてる ⭐⭐⭐
// どこかで freelist の next を誤って上書き?
tls_slab->freelist->next = GARBAGE;
証拠:
- [UNIFIED_FREELIST_INVALID] が多発
- スラブ境界を越えたポインタ
- unified_cache_refill で検出
対処療法との関係:
- validation で DROP → ✅ 安定
- 但し原因は未解決 → ❌ 対症療法
仮説B: Pointer 変換の一貫性崩壊 ⭐⭐⭐
// push 時: user ptr で進む
tls_sll_push(user_ptr); // user offset = +1
// pop 時: base ptr で読む?
base = tls_sll_pop(); // base offset = +0
offset = base + 1; // 再度 +1 ← 二重適用?
証拠:
- [TLS_SLL_NORMALIZE_USERPTR] の多発
- class 1 限定で偏ってる?
対処療法との関係:
- refcount pinning で延期 → ❌ 根本じゃない
仮説C: Slab Index 計算の誤り ⭐⭐
// slab_idx 計算で off-by-one?
int idx = slab_index_for(ss, ptr); // 誤計算 → 0x45c?
証拠:
- next が slab_idx=0x45c(明らかに範囲外)
- 同一 SuperSlab 内だが「計算が狂ってる」
仮説D: SuperSlab 再利用時のゴミ残し ⭐
// 古い SuperSlab を解放
ss_free(ss_old);
// 新しい ss で同じアドレスが再割当
ss_new = ss_alloc(); // ss_old と同じアドレス
// → 古い freelist が残ってる?
📋 次の調査(根本を目指す)
Task 1: 無効 next の発生源特定 ⭐⭐⭐(優先度最高)
実行内容:
# [TLS_SLL_NEXT_INVALID] ログから:
# 1. head slab_idx を記録
# 2. next が指すアドレス (p) から slab_idx_expected を逆算
# 3. 実際の slab_index_for(ss, p) と比較
# 例:
# head p=0x... slab_idx=56
# next p=0x... slab_idx_expected=0x45c(範囲外)
# → slab_index_for() が何を返すか?
期待成果:
- slab_index_for() が間違ってるのか
- freelist が壊れてるのか
- 別の問題か
Task 2: Freelist 破壊の瞬間検出 ⭐⭐⭐(優先度最高)
実行内容:
// tiny_free_local_box に恒常的な prev 検証を追加:
// push 時に:
// prev_meta->next == current?
// current_meta->prev == prev?
//
// prev が合わないなら即座に:
// fprintf(stderr, "[FREELIST_CORRUPTION_DETECTED] ...");
// freelist を drop
期待成果:
- freelist が「いつ、どのタイミングで」破壊されるか
- どのコード経路で壊れるのか
Task 3: userptr 混入源の絞込 ⭐⭐
実行内容:
// クラス1限定で、TLS SLL push 前に強制base化:
hak_base_ptr_t base = ptr_user_to_base(ptr, class_idx);
if (!hak_base_is_valid(base)) {
// A/B test: drop か error か
fprintf(stderr, "[CLASS1_INVALID_BASE] ptr=%p", ptr);
}
期待成果:
- userptr が push されてる頻度
- 発生源(どこから来た userptr か)
⚠️ 現在の対処療法の限界
何が隠蔽されてるのか
| 症状 | 対処方法 | 根本原因 |
|---|---|---|
| [TLS_SLL_NEXT_INVALID] | DROP list | freelist 破壊 |
| [UNIFIED_FREELIST_INVALID] | DROP head | freelist 破壊 |
| [NORMALIZE_USERPTR] | 自動変換 | pointer 変換 bug |
| refcount > 0 skip | defer free | lifecycle bug |
共通点: メモリリーク または 長期的な破壊 の可能性
🔬 科学的接近法
ステップ1: 問題の特性化
Q: 無効 next は「計算誤り」か「上書き」か?
# ログから統計:
# - next slab_idx が「特定の値に偏ってる」?
# → 計算誤りの可能性
# - next slab_idx が「ランダム」?
# → 上書きの可能性
ステップ2: 発生源の限定
Q: freelist が壊れるのは「どのコード経路」か?
# prev 検証で freelist corruption の正確な位置を特定
# → その付近の code を audit
# → 原因が浮かぶ
ステップ3: 根本修正
Q: 修正は「1行」か「10行」か?
対処療法: +3 層(refcount, validation, drop)
根本修正: -1 何か(freelist 計算 OR pointer 変換)
📈 現在の実装の危険性
1. Refcount 遅延解放
✅ SIGSEGV は防ぐ
⚠️ メモリ: refcount > 0 で永遠に free されない
⚠️ 結果: メモリリーク蓄積
リスク: 長時間実行で RSS が増え続ける
2. Freelist DROP
✅ 破損伝播は防ぐ
⚠️ メモリ: DROP されたブロックは回収されない
⚠️ 結果: Freelist 喪失 → 割り当て効率低下
リスク: 長期実行でメモリ枯渇
3. Next Validation DROP
✅ リスト遍走のクラッシュは防ぐ
⚠️ メモリ: リスト全体が失われる可能性
⚠️ 結果: 大量のメモリが「未割り当て」状態
リスク: メモリ使用効率が低下
🎯 推奨される進め方
今すぐやるべき(根本重視)
Task 1A: slab_index_for() の完全監査
- 計算ロジック正確か?
- off-by-one ないか?
- boundary check は十分?
Task 2A: freelist→next の被上書き監視
- prev/next 一貫性チェック追加
- 破壊を「検知」「修復」から「予防」へ
Task 3A: pointer 変換の audit
- user ↔ base 変換が一貫してるか
- クラス別に間違いないか
並行してやるべき(デバッグ)
Metrics 収集:
- [TLS_SLL_NEXT_INVALID] の発生頻度
- [FREELIST_INVALID] の発生頻度
- [NORMALIZE_USERPTR] の発生頻度
- → パターン認識
Memory 監視:
- RSS の増加率(対処療法の影響)
- refcount > 0 の SuperSlab 数
- dropped freelist の総バイト数
📌 結論
現状の評価
✅ 安定性: 達成(SIGSEGV ゼロ)
❌ 健全性: 低下(対処療法の積み重ね)
❌ 根本原因: 未解決(症状だけ見えなくしてる)
危険信号
⚠️ [TLS_SLL_NEXT_INVALID] が「多発」
→ freelist が頻繁に破壊されてる
⚠️ refcount > 0 のスラブが増殖
→ メモリが「解放待ち」で蓄積
⚠️ [NORMALIZE_USERPTR] の多数発生
→ pointer 変換の根本問題が複数ある
推奨アクション
現在: 「症状を隠蔽して安定性を得た」
次へ: 「根本原因を特定して健全性を回復」
Timeline:
Task 1: slab_index_for() audit (1-2h)
Task 2: freelist corruption detection (1-2h)
Task 3: pointer 変換 audit (1h)
↓
根本原因の最終特定(1h)
↓
根本修正(1-3 lines)
Assessment: 今は「安定性優先」から「健全性重視」へシフトする時期。 対処療法の層数が増えすぎる前に、根本原因に向き合おう。
Document created: 2025-12-03 Analysis: Symptoms are being suppressed, not cured Risk Level: MEDIUM (stability achieved, but long-term viability uncertain)