# 帳票設計書 17-ThreadCrashReporter

## 概要

本ドキュメントは、clangdにおけるスレッドクラッシュ情報を報告するThreadCrashReporterの設計仕様を定義する。ThreadCrashReporterは、スレッドごとのクラッシュハンドラを管理し、シグナル受信時にスレッド固有の診断情報を出力する仕組みを提供する。

### 本帳票の処理概要

ThreadCrashReporterは、clangd Language Serverのマルチスレッド処理において、特定のスレッドがクラッシュした際に、そのスレッドで実行中だった処理に関するコンテキスト情報を報告するためのインフラストラクチャである。

**業務上の目的・背景**：clangdは複数のリクエストを並列処理するマルチスレッドサーバーである。クラッシュが発生した場合、どのリクエストを処理中だったか、どのような状態だったかを把握することが問題解決に重要である。ThreadCrashReporterは、スレッドローカルなコールバック機構により、クラッシュ時にスレッド固有の診断情報を提供する。

**帳票の利用シーン**：
- clangdがSIGSEGV等のシグナルでクラッシュした際
- 内部エラーによりプロセスが異常終了した際
- デバッグ・問題調査時

**主要な出力内容**：
1. スレッドごとに登録されたコールバックの実行結果
2. 処理中だったリクエストの情報
3. スレッドのコンテキスト情報

**帳票の出力タイミング**：シグナルハンドラ（sys::AddSignalHandler経由）が呼び出された時点で出力される。

**帳票の利用者**：clangd開発者、LSPクライアント開発者、言語サーバー利用者

## 帳票種別

クラッシュ診断レポート / デバッグレポート

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | 標準エラー出力 | N/A | クラッシュ時に自動出力 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | テキスト（標準エラー出力） |
| 用紙サイズ | N/A |
| 向き | N/A |
| ファイル名 | N/A |
| 出力方法 | コールバック関数経由 |
| 文字コード | システムロケール依存 |

### 出力設定

| 項目 | 内容 |
|-----|------|
| 呼び出し順序 | LIFO（後入れ先出し） |
| ネスト対応 | 有（スタック管理） |
| スレッド安全性 | thread_local使用 |

## 帳票レイアウト

### レイアウト概要

出力内容はコールバック関数の実装に依存する。典型的な出力形式は以下の通り。

```
ThreadCrashReporter: {コンテキスト情報}
Processing request: {リクエスト情報}
File: {ファイルパス}
...
```

### 出力項目

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | コールバック出力 | 登録されたコールバックの出力 | SignalCallback | 自由形式 |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| クラッシュ発生 | シグナル受信 | Yes |
| コールバック登録 | ThreadCrashReporterインスタンス存在 | Yes |

### ソート順

N/A

### 改ページ条件

N/A

## データベース参照仕様

### 参照テーブル一覧

本帳票はデータベースを使用しない。

| データソース | 用途 | 取得方法 |
|-------------|------|---------|
| thread_local変数 | 現在のレポーター | CurrentReporter |
| コールバック関数 | 診断情報生成 | Callback() |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| - | - | - | 計算項目なし |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[シグナル受信] --> B[sys::AddSignalHandler呼び出し]
    B --> C[runCrashHandlers呼び出し]
    C --> D{CurrentReporter != null?}
    D -->|Yes| E[Callback実行]
    E --> F[Next = Reporter->Next]
    F --> D
    D -->|No| G[終了]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| 二重登録 | 同一スレッドで二重登録 | assert失敗 | コード修正 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | スレッドごとに1レポーター |
| 目標出力時間 | 即座（シグナルハンドラ内） |
| 同時出力数上限 | スレッドごとに1 |

## セキュリティ考慮事項

- コールバック内でアクセスするデータはクラッシュ時に不整合状態の可能性がある
- 非同期シグナル安全でない関数の使用は避けるべき
- ファイルパス等の情報が出力に含まれる可能性

## 備考

- コンストラクタでCurrentReporterにthisを設定
- デストラクタでCurrentReporterをNextに復元
- atomic_signal_fenceでメモリオーダリングを保証
- ムーブ・コピーは禁止（=delete）

---

## コードリーディングガイド

本帳票を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ThreadCrashReporter.h | `clang-tools-extra/clangd/support/ThreadCrashReporter.h` | ThreadCrashReporterクラス定義（19-53行目） |

**読解のコツ**:
- `SignalCallback`はunique_function<void()>型
- `Next`ポインタでスタック構造を実現

#### Step 2: 実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ThreadCrashReporter.cpp | `clang-tools-extra/clangd/support/ThreadCrashReporter.cpp` | thread_local変数CurrentReporter（15行目） |
| 2-2 | ThreadCrashReporter.cpp | `clang-tools-extra/clangd/support/ThreadCrashReporter.cpp` | runCrashHandlers（17-33行目） |
| 2-3 | ThreadCrashReporter.cpp | `clang-tools-extra/clangd/support/ThreadCrashReporter.cpp` | コンストラクタ（35-42行目） |
| 2-4 | ThreadCrashReporter.cpp | `clang-tools-extra/clangd/support/ThreadCrashReporter.cpp` | デストラクタ（44-50行目） |

**主要処理フロー**:
1. **35-38行目**: コンストラクタでNextを設定し、CurrentReporterを更新
2. **41行目**: atomic_signal_fenceで順序保証
3. **17-32行目**: runCrashHandlersでLIFO順にコールバック実行

### プログラム呼び出し階層図

```
sys::AddSignalHandler (シグナルハンドラ登録)
    │
    └─ runCrashHandlers (ThreadCrashReporter.cpp:17)
           │
           ├─ CurrentReporter取得 (thread_local)
           │
           └─ while (Reporter)
                  ├─ Reporter->Callback()
                  └─ Reporter = Reporter->Next
```

### データフロー図

```
[登録]                     [実行]                        [出力]

ThreadCrashReporter ──▶ CurrentReporter設定 ─────────┐
コンストラクタ                │                       │
                             │                       │
                       ┌─────┴─────┐                 │
                       │  スタック  │                 │
                       │  構造管理  │                 │
                       └─────┬─────┘                 │
                             │                       │
シグナル受信 ────────────▶ runCrashHandlers ──▶ Callback ──▶ stderr
                                                     │
ThreadCrashReporter ──▶ CurrentReporter復元 ─────────┘
デストラクタ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ThreadCrashReporter.h | `clang-tools-extra/clangd/support/ThreadCrashReporter.h` | ヘッダー | クラス定義 |
| ThreadCrashReporter.cpp | `clang-tools-extra/clangd/support/ThreadCrashReporter.cpp` | ソース | 実装 |
| Signals.h | `llvm/include/llvm/Support/Signals.h` | ヘッダー | シグナルハンドラ |
