# 機能設計書 5-イベントループ終了

## 概要

本ドキュメントは、libuvライブラリにおけるイベントループ終了機能（`uv_loop_close()`）の設計仕様を記述する。

### 本機能の処理概要

`uv_loop_close()`は、イベントループを終了し、確保されたリソースを解放する関数である。アクティブなリクエストやユーザーハンドルが残っている場合は`UV_EBUSY`エラーを返す。正常終了時にはプラットフォーム固有のバックエンドリソース、同期プリミティブ、内部フィールド等を解放する。

**業務上の目的・背景**：イベントループのライフサイクル終了時にリソースリークを防ぐために必要な処理である。ファイルディスクリプタ、ミューテックス、メモリ等のシステムリソースを適切に解放することで、長時間稼働するアプリケーションのリソース枯渇を防止する。

**機能の利用シーン**：
- アプリケーション終了前のクリーンアップ処理
- テストケースで作成したイベントループの後始末
- 一時的に使用したカスタムイベントループの解放

**主要な処理内容**：
1. アクティブリクエストの存在確認（残っていればUV_EBUSY）
2. ユーザーハンドルの存在確認（残っていればUV_EBUSY）
3. プラットフォーム固有リソースの解放（`uv__loop_close()`）
4. デバッグ時のmemset（-1でクリア、dataは保持）
5. デフォルトループの場合、`default_loop_ptr`をNULLにリセット

**関連システム・外部連携**：プラットフォーム固有のI/Oバックエンド（kqueue FD、epoll FD）の解放。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 6 | イベントループ | 主機能 | uv_loop_close()によるイベントループ終了・リソース解放のAPI定義 |
| 33 | 基本事項 | 補助機能 | uv_loop_close()によるリソース解放の説明 |

## 機能種別

リソース解放 / 終了処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| loop | uv_loop_t* | Yes | 終了対象のイベントループ | NULLチェックなし |

### 入力データソース

`uv_loop_init()`で初期化済みのイベントループ。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | int | 成功時は0、ハンドル/リクエストが残っている場合はUV_EBUSY |

### 出力先

関数の戻り値。成功時はイベントループ構造体のリソースが全て解放される。

## 処理フロー

### 処理シーケンス

```
1. アクティブリクエスト確認
   └─ uv__has_active_reqs(loop)がtrueならUV_EBUSY返却
2. ユーザーハンドル確認
   └─ handle_queueを走査し、UV_HANDLE_INTERNALでないハンドルがあればUV_EBUSY返却
3. 内部リソース解放（uv__loop_close(loop)）
   a. シグナルループクリーンアップ
   b. プラットフォームバックエンド削除
   c. 非同期ハンドル停止
   d. emfile_fd / backend_fd のクローズ
   e. ワークキューの空確認とミューテックス解放
   f. cloexecロック解放
   g. ウォッチャー配列の解放
   h. メトリクスミューテックス解放
   i. 内部フィールドメモリ解放
4. デバッグモードでのmemset（-1クリア、data保持）
5. デフォルトループポインタのリセット
   └─ loop == default_loop_ptrならNULLに設定
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{アクティブリクエストあり?}
    B -->|Yes| C[UV_EBUSY返却]
    B -->|No| D{ユーザーハンドルあり?}
    D -->|Yes| C
    D -->|No| E[uv__loop_close実行]
    E --> F{NDEBUGモード?}
    F -->|No| G[memset -1 + data復元]
    F -->|Yes| H{デフォルトループ?}
    G --> H
    H -->|Yes| I[default_loop_ptr = NULL]
    H -->|No| J[0を返却]
    I --> J
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 事前ハンドルクローズ必須 | すべてのユーザーハンドルをuv_close()で閉じてからuv_loop_close()を呼ぶ必要がある | 常時 |
| BR-02 | リクエスト完了必須 | すべてのアクティブリクエストが完了してから呼ぶ必要がある | 常時 |
| BR-03 | 内部ハンドル除外 | UV_HANDLE_INTERNALフラグが付いたハンドルはEBUSY判定から除外される | 常時 |
| BR-04 | デフォルトループリセット | デフォルトループをクローズした場合、次回uv_default_loop()で再初期化される | デフォルトループの場合 |

### 計算ロジック

特になし。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_EBUSY | リソースビジー | アクティブなリクエストが残っている | すべてのリクエストが完了するまで待機 |
| UV_EBUSY | リソースビジー | ユーザーハンドルが残っている | すべてのハンドルをuv_close()で閉じる |

### リトライ仕様

UV_EBUSY返却時は、残っているハンドル/リクエストを処理してから再試行する。典型的には`uv_walk()`で残ハンドルを列挙し、`uv_close()`で閉じた後、`uv_run()`でクローズコールバックを処理してから再度`uv_loop_close()`を呼び出す。

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

該当なし。

## パフォーマンス要件

終了処理のため、パフォーマンス要件は特にない。

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

- デバッグビルドでは構造体を-1で上書きし、解放後のメモリ使用を検出可能にしている
- ユーザーデータ（data）はデバッグクリア時も保持される

## 備考

- `uv_loop_delete()`は非推奨であり、`uv_loop_close()`の使用が推奨される
- `uv_loop_close()`は内部的に`uv__loop_close()`を呼び出す（プラットフォーム固有の終了処理）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | **1941-1956行目**: uv_loop_s構造体。active_reqs, handle_queue, internal_fieldsなどのクローズ対象フィールド |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | uv.h | `include/uv.h` | **292行目**: `uv_loop_close()`のAPI宣言 |
| 2-2 | uv-common.c | `src/uv-common.c` | **878-905行目**: `uv_loop_close()`の実装 |

**主要処理フロー**:
1. **885-886行目**: `uv__has_active_reqs(loop)`でアクティブリクエスト確認
2. **888-891行目**: handle_queueを走査し、INTERNALでないハンドルがあればUV_EBUSY
3. **894行目**: `uv__loop_close(loop)`で内部リソース解放
4. **897-899行目**: デバッグ時のmemset(-1)とdata復元
5. **901-902行目**: デフォルトループならdefault_loop_ptrをNULLリセット

#### Step 3: 内部リソース解放を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | loop.c | `src/unix/loop.c` | **168-211行目**: `uv__loop_close()`の実装。シグナル、プラットフォーム、非同期、FD、ミューテックス等の段階的解放 |

**主要処理フロー**:
- **171行目**: `uv__signal_loop_cleanup(loop)` - シグナル処理のクリーンアップ
- **172行目**: `uv__platform_loop_delete(loop)` - kqueue/epoll FDの解放
- **173行目**: `uv__async_stop(loop)` - 非同期ハンドルの停止
- **175-183行目**: emfile_fd、backend_fdのクローズ
- **185-189行目**: ワークキューの空確認とミューテックス解放
- **195行目**: cloexecロック解放
- **203-205行目**: ウォッチャー配列のメモリ解放
- **207-210行目**: 内部フィールドのメトリクスミューテックス解放とメモリ解放

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

```
uv_loop_close(loop)                      [src/uv-common.c:878]
    |
    +-- uv__has_active_reqs(loop)         [マクロ]
    |
    +-- uv__queue_foreach() + UV_HANDLE_INTERNAL確認
    |
    +-- uv__loop_close(loop)              [src/unix/loop.c:168]
    |       +-- uv__signal_loop_cleanup()
    |       +-- uv__platform_loop_delete()
    |       +-- uv__async_stop()
    |       +-- uv__close(emfile_fd)
    |       +-- uv__close(backend_fd)
    |       +-- uv_mutex_destroy(wq_mutex)
    |       +-- uv_rwlock_destroy(cloexec_lock)
    |       +-- uv__free(watchers)
    |       +-- uv_mutex_destroy(metrics.lock)
    |       +-- uv__free(internal_fields)
    |
    +-- [NDEBUG off] memset(-1) + data復元
    |
    └-- default_loop_ptr = NULL (if default loop)
```

### データフロー図

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

uv_loop_t* loop     -->  EBUSY判定                       -->  int (0 or UV_EBUSY)
(初期化済み)             |                                    |
                         +-- 内部リソース解放                 +-- FD/メモリ/ロック解放
                         +-- default_loop_ptr管理             +-- ポインタリセット
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | uv_loop_close()のAPI宣言 |
| uv-common.c | `src/uv-common.c` | ソース | uv_loop_close()の共通実装 |
| loop.c | `src/unix/loop.c` | ソース | uv__loop_close()のUnix固有実装 |
