# 通知設計書 11-BrokenPipeException

## 概要

本ドキュメントは、HH\Lib\OS\BrokenPipeException例外クラスの設計を記述する。この例外は、パイプが破損した状態でのI/O操作時に発生するエラーを通知するためのものである。

### 本通知の処理概要

BrokenPipeExceptionは、OSレベルでパイプまたはソケットが予期せず切断された際に、アプリケーションに対してエラー状態を通知する例外クラスである。POSIX errnoのEPIPE（パイプ破損）およびESHUTDOWN（ソケットシャットダウン済み）エラーに対応し、ConnectionExceptionの具象クラスとして実装されている。

**業務上の目的・背景**：I/O操作において、通信相手側が接続を切断した場合や、パイプの読み取り側が閉じられた状態で書き込みを行おうとした場合、アプリケーションはこの状態を適切にハンドリングする必要がある。BrokenPipeExceptionは、このようなエラー状態を型安全に表現し、キャッチ可能な例外として提供することで、エラーハンドリングの明確化と保守性の向上を実現する。

**通知の送信タイミング**：この例外は以下のような状況で発生する。(1) パイプの読み取り側が閉じられた状態で書き込みを実行した場合。(2) ソケット接続がシャットダウンされた後にデータ送受信を試みた場合。(3) BufferedReaderで指定サイズのデータを読み取る前にEOFに到達した場合。(4) readUntilxAsyncでマーカーが見つからずにEOFに到達した場合。

**通知の受信者**：この例外は、I/O操作を実行しているコード（呼び出し元）に対してスローされる。具体的には、パイプやソケットを使用した読み書き処理を実装しているアプリケーションコードが受信者となる。

**通知内容の概要**：例外オブジェクトには、発生したerrnoコード（EPIPEまたはESHUTDOWN）とエラーメッセージが含まれる。getErrno()メソッドにより具体的なエラーコードを取得可能である。

**期待されるアクション**：受信者は、この例外をキャッチして適切なエラーハンドリングを行うことが期待される。典型的には、接続の再確立、代替処理の実行、またはユーザーへのエラー通知などを行う。

## 通知種別

例外スロー（Exception Throw）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（例外スロー） |
| 優先度 | 高（エラー通知） |
| リトライ | N/A（例外のため） |

### 送信先決定ロジック

例外は、I/O操作を実行した呼び出し元のコードに対してスローされる。コールスタックに沿って上位に伝播し、適切なtry-catchブロックで捕捉される。

## 通知テンプレート

### 例外メッセージの場合

| 項目 | 内容 |
|-----|------|
| 例外クラス | HH\Lib\OS\BrokenPipeException |
| 親クラス | HH\Lib\OS\ConnectionException |
| 形式 | 文字列メッセージ |

### 本文テンプレート

```
{ERRNO_NAME}({ERRNO_VALUE}): {ERROR_MESSAGE}
```

例：
- `EPIPE(32): Reached end of file before requested size`
- `EPIPE(32): Marker/suffix not found before end of file`
- `EPIPE(32): No more lines to read.`

### 添付ファイル

該当なし（例外通知のため）

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| ERRNO_NAME | エラー番号の名称（EPIPE/ESHUTDOWN） | OS\Errno::EPIPE または OS\Errno::ESHUTDOWN | Yes |
| ERRNO_VALUE | エラー番号の数値 | errno.h定義値 | Yes |
| ERROR_MESSAGE | エラーの詳細メッセージ | 呼び出し元から提供 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| I/O操作 | パイプへの書き込み | 読み取り側が閉じている | write()でEPIPE発生時 |
| I/O操作 | ソケットへの送信 | ソケットがシャットダウン済み | send()でESHUTDOWN発生時 |
| API呼び出し | BufferedReader::readFixedSizeAsync | 要求サイズ到達前にEOF | 固定サイズ読み取りの途中でEOF |
| API呼び出し | BufferedReader::readUntilxAsync | マーカー未検出でEOF | 指定サフィックスが見つからずEOF |
| API呼び出し | BufferedReader::readLinexAsync | 行データなしでEOF | 読み取り可能な行がない |
| API呼び出し | BufferedReader::readByteAsync | データなしでEOF | 読み取り可能なバイトがない |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 正常なEOF | 単純なEOFはnullまたは空文字列を返し、例外はスローしない |
| BlockingIO | EAGAIN/EWOULDBLOCKの場合はBlockingIOExceptionをスロー |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[I/O操作実行] --> B{エラー発生?}
    B -->|No| C[正常完了]
    B -->|Yes| D{errno値確認}
    D -->|EPIPE| E[BrokenPipeException生成]
    D -->|ESHUTDOWN| E
    D -->|その他| F[他のErrnoException]
    E --> G[メッセージ設定]
    G --> H[例外スロー]
    H --> I[呼び出し元でキャッチ]
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（ファイルシステム/OS例外のため）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| EPIPE | パイプ破損 | 接続再確立または処理終了 |
| ESHUTDOWN | ソケットシャットダウン | 新規接続確立 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | アプリケーション依存 |
| リトライ間隔 | アプリケーション依存 |
| リトライ対象エラー | EPIPEは再接続後に再試行可能 |

## 配信設定

### レート制限

該当なし（例外スローのため）

### 配信時間帯

該当なし

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

- エラーメッセージに機密情報を含めないこと
- スタックトレースの外部公開に注意

## 備考

- BrokenPipeExceptionはConnectionExceptionを継承しており、接続関連エラーとして一括でキャッチ可能
- EPIPEとESHUTDOWNの両方を処理するため、コンストラクタでerrnoコードを受け取る設計
- _getValidErrnos()メソッドで有効なerrnoの集合を公開

---

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

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

### 推奨読解順序

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

まず、Errno列挙型とErrnoExceptionの継承階層を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Errno.php | `src/os/Errno.php` | EPIPEとESHUTDOWNの定義（70行目、151行目） |
| 1-2 | ErrnoException.php | `src/os/ErrnoException.php` | 例外クラス階層の理解（52-125行目） |

**読解のコツ**: HackのenumはPHPとは異なり、型安全な列挙型である。`as int`は基底型を示す。

#### Step 2: エントリーポイントを理解する

例外がスローされる起点となるコードを特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Errno.php (private) | `src/os/_Private/Errno.php` | throw_errno関数の実装（70-85行目） |

**主要処理フロー**:
1. **70-76行目**: throw_errno関数の定義、フォーマット文字列の処理
2. **77-81行目**: errno値の検証（0は成功を示すため不正）
3. **82-84行目**: errno名の取得と適切な例外クラスの選択・スロー

#### Step 3: 例外クラスの実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ErrnoException.php | `src/os/ErrnoException.php` | BrokenPipeExceptionの実装（111-125行目） |

**主要処理フロー**:
- **111行目**: final classとしてConnectionExceptionを継承
- **112-120行目**: コンストラクタでerrno値の検証を実施
- **122-124行目**: _getValidErrnos()でEPIPEとESHUTDOWNを返却

#### Step 4: 使用例を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | BufferedReader.php | `src/io/BufferedReader.php` | BrokenPipeExceptionの使用箇所（136-139行目、193行目、231-234行目） |
| 4-2 | PipeTest.php | `tests/io/PipeTest.php` | テストでの例外キャッチ例（182-186行目、234-237行目） |

**主要処理フロー**:
- **BufferedReader.php 136-139行目**: readUntilxAsyncでマーカーが見つからない場合
- **BufferedReader.php 193行目**: readLinexAsyncで行がない場合
- **BufferedReader.php 231-234行目**: readFixedSizeAsyncでEOFに達した場合

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

```
アプリケーションコード
    │
    ├─ BufferedReader::readFixedSizeAsync()
    │      └─ throw new BrokenPipeException(EPIPE, message)
    │
    ├─ BufferedReader::readUntilxAsync()
    │      └─ throw new BrokenPipeException(EPIPE, message)
    │
    ├─ BufferedReader::readLinexAsync()
    │      └─ throw new BrokenPipeException(EPIPE, message)
    │
    └─ _Private\_OS\throw_errno()
           └─ get_throw_errno_impl()
                  └─ throw new BrokenPipeException($code, $msg)
```

### データフロー図

```
[入力]               [処理]                           [出力]

I/O操作呼び出し ───▶ OSシステムコール実行 ───▶ errno取得
                         │
                         ▼
                    errno判定
                    (EPIPE/ESHUTDOWN)
                         │
                         ▼
                    BrokenPipeException生成
                         │
                         ▼
                    例外スロー ───▶ 呼び出し元のcatchブロック
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ErrnoException.php | `src/os/ErrnoException.php` | ソース | BrokenPipeExceptionクラス定義（111-125行目） |
| Errno.php | `src/os/Errno.php` | ソース | EPIPE/ESHUTDOWN定数定義 |
| Errno.php | `src/os/_Private/Errno.php` | ソース | throw_errno関数実装 |
| BufferedReader.php | `src/io/BufferedReader.php` | ソース | 例外使用箇所 |
| wrap_impl.php | `src/os/_Private/wrap_impl.php` | ソース | OSエラーラッパー |
| PipeTest.php | `tests/io/PipeTest.php` | テスト | 例外ハンドリングテスト |
