# 機能設計書 35-シャットダウン

## 概要

本ドキュメントは、libuvにおけるストリームシャットダウン機能（uv_shutdown()）の設計仕様を記述する。ストリームの書き込み側を半二重クローズする機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：TCP接続などの双方向ストリームにおいて、書き込み側のみを閉じて「これ以上データを送信しない」ことを通信相手に通知する必要がある。uv_shutdown()は書き込み側をシャットダウンし、相手側にEOFを送信する。読み取り側は引き続きデータを受信できるため、プロトコルの正常終了シーケンス（graceful shutdown）を実現できる。

**機能の利用シーン**：HTTPレスポンスの送信完了後にサーバーが接続のシャットダウンを開始する場合、クライアントが全データ送信後にシャットダウンする場合に使用される。

**主要な処理内容**：
1. ストリームの書き込み可能状態チェック
2. シャットダウンリクエストの初期化
3. UV_HANDLE_WRITABLEフラグのクリア
4. 書き込みキューが空の場合は即座にI/Oフィードでシャットダウンをトリガー
5. 実際のshutdown(2)システムコールはuv__drain()内で遅延実行される

**関連システム・外部連携**：OSのshutdown(fd, SHUT_WR)システムコール。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | ストリーム | 主機能 | uv_shutdown()による書き込み側シャットダウンのAPI定義 |

## 機能種別

接続管理処理（半二重クローズ）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| req | uv_shutdown_t* | Yes | シャットダウンリクエスト | NULLでないこと |
| stream | uv_stream_t* | Yes | シャットダウン対象のストリーム | UV_TCP, UV_TTY, UV_NAMED_PIPEのいずれか |
| cb | uv_shutdown_cb | No | シャットダウン完了コールバック | NULLでも可 |

### 入力データソース

アプリケーションコードからの直接呼び出し。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | int | 0: 成功、負値: エラーコード |
| コールバック引数 req | uv_shutdown_t* | シャットダウンリクエスト |
| コールバック引数 status | int | 0: 成功、負値: エラー |

### 出力先

コールバック（uv_shutdown_cb）を通じてアプリケーションにシャットダウン完了を通知。

## 処理フロー

### 処理シーケンス

```
1. 事前チェック
   ├─ ストリーム型がTCP/TTY/パイプであることをassert
   ├─ UV_HANDLE_WRITABLEフラグチェック（なければUV_ENOTCONN）
   ├─ UV_HANDLE_SHUTチェック（既にシャットダウン済み→UV_ENOTCONN）
   ├─ シャットダウン進行中チェック（→UV_ENOTCONN）
   └─ クローズ中チェック（→UV_ENOTCONN）

2. リクエスト初期化
   ├─ uv__req_init()でリクエスト登録
   ├─ handle、cbの設定
   └─ stream->shutdown_req = req

3. UV_HANDLE_WRITABLEフラグをクリア

4. シャットダウントリガー
   ├─ write_queueが空の場合 → uv__io_feed()で即座にトリガー
   └─ write_queueにデータがある場合 → データ送信完了後にuv__drain()経由

5. uv__drain()内での実行
   ├─ クローズ中の場合 → UV_ECANCELED
   ├─ shutdown(fd, SHUT_WR)システムコール
   └─ 成功時 → UV_HANDLE_SHUTフラグ設定
```

### フローチャート

```mermaid
flowchart TD
    A[uv_shutdown 呼び出し] --> B{書き込み可能?}
    B -->|No| C[UV_ENOTCONN 返却]
    B -->|Yes| D[リクエスト初期化]
    D --> E[UV_HANDLE_WRITABLE クリア]
    E --> F{write_queue 空?}
    F -->|Yes| G[uv__io_feed で即時トリガー]
    F -->|No| H[書き込み完了を待機]
    G --> I[uv__drain 実行]
    H --> I
    I --> J[shutdown fd SHUT_WR]
    J --> K[コールバック呼び出し]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-35-01 | 遅延実行 | shutdown(2)はuv__drain()内で遅延実行される（キュー内データ送信後） | 常時 |
| BR-35-02 | 書き込み不可化 | uv_shutdown()呼び出し直後にUV_HANDLE_WRITABLEがクリアされ、以降の書き込みは拒否される | 常時 |
| BR-35-03 | 読み取り継続 | シャットダウン後もストリームからの読み取りは可能 | 常時 |
| BR-35-04 | クローズ中キャンセル | ストリームがクローズ中にシャットダウンが実行された場合、UV_ECANCELEDがコールバックに渡される | クローズ中 |

### 計算ロジック

特になし。

## データベース操作仕様

該当なし。

### 操作別データベース影響一覧

該当なし。

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_ENOTCONN | 状態エラー | 書き込み不可、既にシャットダウン済み、シャットダウン中、クローズ中 | ストリームの状態を確認 |
| UV_ECANCELED | キャンセル | ストリームがクローズされた場合（コールバック経由） | 正常系として処理 |
| errno系エラー | システムエラー | shutdown(2)の失敗（コールバック経由） | エラー内容を確認 |

### リトライ仕様

シャットダウンは1回のみ実行可能。リトライは不要。

## トランザクション仕様

該当なし。

## パフォーマンス要件

- 書き込みキューが空の場合はuv__io_feed()で即座にイベントをトリガーし、次のイベントループイテレーションでshutdown(2)を実行

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

- シャットダウン後は書き込みが不可能になるため、意図しないデータ送信を防止できる

## 備考

- uv_shutdown_t構造体はuv_req_tのサブクラスで、handle, cbフィールドを持つ
- Unix版ではshutdown(fd, SHUT_WR)、Windows版ではハンドル型に応じた処理（パイプの場合はuv__pipe_shutdown）が行われる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | **451-453行目**: uv_shutdown()のAPI宣言 |
| 1-2 | uv.h | `include/uv.h` | **455-460行目**: uv_shutdown_s構造体の定義（handle, cb） |

**読解のコツ**: uv_shutdown_tはuv_req_tのサブクラスで、UV_REQ_FIELDSを継承する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | stream.c | `src/unix/stream.c` | **1161-1187行目**: uv_shutdown()のUnix実装 |

**主要処理フロー**:
1. **1162-1164行目**: ストリーム型アサーション
2. **1166-1171行目**: 状態チェック（WRITABLE、SHUT、shutting、closing）
3. **1177-1181行目**: リクエスト初期化、shutdown_req設定、WRITABLEクリア
4. **1183-1184行目**: キュー空ならuv__io_feed()で即時トリガー

#### Step 3: 実際のシャットダウン処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | stream.c | `src/unix/stream.c` | **625-658行目**: uv__drain()内のシャットダウン処理 |

**主要処理フロー**:
- **635-636行目**: シャットダウン中でなければreturn
- **641-657行目**: shutdown(fd, SHUT_WR)の実行とUV_HANDLE_SHUTフラグ設定

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

```
uv_shutdown(req, stream, cb)
    ├─ 状態チェック
    ├─ uv__req_init(loop, req, UV_SHUTDOWN)
    ├─ stream->flags &= ~UV_HANDLE_WRITABLE
    └─ uv__io_feed(loop, &stream->io_watcher) [キュー空時]
           └─ uv__stream_io() [イベントループ内]
                  └─ uv__drain(stream)
                         ├─ shutdown(fd, SHUT_WR)
                         ├─ stream->flags |= UV_HANDLE_SHUT
                         └─ req->cb(req, status)
```

### データフロー図

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

req, stream, cb ───▶ uv_shutdown()                 ───▶ 0 or エラー
                       │
                       ├─ リクエスト初期化
                       ├─ WRITABLEクリア
                       └─ [キュー空時] io_feed
                              └─ uv__drain()
                                    ├─ shutdown(fd, SHUT_WR) ───▶ TCP FINパケット
                                    └─ cb(req, status)      ───▶ アプリケーション
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | uv_shutdown()/uv_shutdown_tのAPI宣言と構造体定義 |
| stream.c | `src/unix/stream.c` | ソース | Unix版uv_shutdown()とuv__drain()の実装 |
| stream.c | `src/win/stream.c` | ソース | Windows版uv_shutdown()の実装 |
