# 機能設計書 8-イベントループfork対応

## 概要

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

### 本機能の処理概要

`uv_loop_fork()`は、`fork()`システムコール後に子プロセス内でイベントループを再初期化する関数である。fork後に子プロセスでイベントループを引き続き使用するために、I/Oバックエンド、非同期通知機構、シグナル処理のリセットおよびウォッチャーの再登録を行う。

**業務上の目的・背景**：Unix系OSではfork()によるプロセス複製が一般的であるが、epoll/kqueue等のI/Oイベント通知機構はforkをまたいで正しく動作しない。子プロセスでイベントループを再利用するためには、これらのカーネルリソースを再作成する必要がある。

**機能の利用シーン**：
- マルチプロセスサーバー（pre-fork型）で子プロセスがイベントループを使用する場合
- fork後に子プロセスで独自のイベント処理を行う場合

**主要な処理内容**：
1. I/Oバックエンドの再初期化（`uv__io_fork()`）- epoll/kqueue FDの再作成
2. 非同期通知機構の再初期化（`uv__async_fork()`）- eventfd/pipeの再作成
3. シグナル処理の再初期化（`uv__signal_loop_fork()`）- シグナルパイプの再作成
4. 既存ウォッチャーの再登録 - eventsを0にリセットしwatcher_queueに再挿入

**関連システム・外部連携**：fork()システムコール、epoll/kqueue等のカーネルI/O機構。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 6 | イベントループ | 主機能 | uv_loop_fork()によるfork後ループ再初期化のAPI定義 |

## 機能種別

再初期化処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| loop | uv_loop_t* | Yes | fork後に再初期化するイベントループ | NULLチェックなし |

### 入力データソース

fork()前に初期化されていたイベントループ構造体。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | int | 成功時は0、失敗時は負のエラーコード |

### 出力先

イベントループ構造体の内部状態が再初期化される。

## 処理フロー

### 処理シーケンス

```
1. I/Oバックエンドの再初期化
   └─ uv__io_fork(loop) - epoll/kqueue FDの再作成
2. 非同期通知の再初期化
   └─ uv__async_fork(loop) - eventfd/pipeの再作成
3. シグナル処理の再初期化
   └─ uv__signal_loop_fork(loop) - シグナルパイプの再作成
4. ウォッチャーの再登録
   └─ 全ウォッチャーを走査し、eventsを0にリセットしてwatcher_queueに再挿入
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[uv__io_fork]
    B --> C{成功?}
    C -->|No| D[エラー返却]
    C -->|Yes| E[uv__async_fork]
    E --> F{成功?}
    F -->|No| D
    F -->|Yes| G[uv__signal_loop_fork]
    G --> H{成功?}
    H -->|No| D
    H -->|Yes| I[ウォッチャー再登録ループ]
    I --> J[0を返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | fork直後に呼び出し | fork()直後、他のlibuv APIを呼ぶ前にuv_loop_fork()を呼ぶ必要がある | fork後 |
| BR-02 | 子プロセスのみ | 親プロセスでは呼び出す必要はない | 子プロセス |
| BR-03 | ウォッチャー再登録 | 既存のウォッチャーはeventsを0にリセットして再登録キューに挿入する | 常時 |

### 計算ロジック

ウォッチャー再登録ループ:
```c
for (i = 0; i < loop->nwatchers; i++) {
    w = loop->watchers[i];
    if (w == NULL) continue;
    if (w->pevents != 0 && uv__queue_empty(&w->watcher_queue)) {
        w->events = 0;  // 再登録を強制
        uv__queue_insert_tail(&loop->watcher_queue, &w->watcher_queue);
    }
}
```

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 負のエラーコード | I/O再初期化失敗 | epoll/kqueue FDの再作成失敗 | ファイルディスクリプタの空きを確保 |
| 負のエラーコード | 非同期再初期化失敗 | eventfd/pipeの再作成失敗 | リソースを確認して再試行 |
| 負のエラーコード | シグナル再初期化失敗 | シグナルパイプの再作成失敗 | リソースを確認して再試行 |

### リトライ仕様

リトライ機構は組み込まれていない。各段階で失敗した場合は即座にエラーを返す。

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

該当なし。各再初期化処理は順次実行される。途中でエラーが発生した場合、以降の再初期化は実行されない。

## パフォーマンス要件

fork後の一度きりの処理であり、パフォーマンス要件は特にない。

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

- fork後のファイルディスクリプタ管理に注意が必要
- macOSでは、fork後にCFRunLoopが使用不可になるため、FSEventsベースのファイル監視が機能しなくなる（kqueueにフォールバック）

## 備考

- macOSでは、fork後にCFRunLoopが使えなくなるため、`uv__has_forked_with_cfrunloop`フラグが設定され、FSEventsの代わりにkqueueベースのファイル監視にフォールバックする
- fork後のイベントループの動作は完全には保証されず、一部の機能が制限される場合がある

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | **1941-1956行目**: uv_loop_s構造体。watchers, nwatchers等のフィールド |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | uv.h | `include/uv.h` | **308行目**: `uv_loop_fork()`のAPI宣言 |
| 2-2 | loop.c | `src/unix/loop.c` | **135-165行目**: `uv_loop_fork()`の実装 |

**主要処理フロー**:
1. **140-142行目**: `uv__io_fork(loop)` - I/Oバックエンドの再初期化
2. **144-146行目**: `uv__async_fork(loop)` - 非同期通知の再初期化
3. **148-150行目**: `uv__signal_loop_fork(loop)` - シグナル処理の再初期化
4. **153-162行目**: ウォッチャー再登録ループ。`w->events = 0`で再登録を強制し、`watcher_queue`に再挿入

#### Step 3: macOS固有のfork対応を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | kqueue.c | `src/unix/kqueue.c` | **72-92行目**: macOSでのfork対応。CFRunLoop/FSEventsの無効化 |

**主要処理フロー**:
- **75-91行目**: `loop->cf_state`がある場合、`uv__has_forked_with_cfrunloop`を設定し、cf_stateを解放・NULLに設定

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

```
uv_loop_fork(loop)                       [src/unix/loop.c:135]
    |
    +-- uv__io_fork(loop)                [プラットフォーム固有]
    |       └── epoll/kqueue FDの再作成
    |
    +-- uv__async_fork(loop)             [src/unix/async.c]
    |       └── eventfd/pipeの再作成
    |
    +-- uv__signal_loop_fork(loop)       [src/unix/signal.c]
    |       └── シグナルパイプの再作成
    |
    └── [ウォッチャー再登録ループ]
            └── w->events = 0 + watcher_queueに再挿入
```

### データフロー図

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

uv_loop_t* loop     -->  各サブシステム再初期化           -->  int (0 or エラー)
(fork前の状態)           |                                    |
                         +-- I/O FD再作成                     +-- 新しいbackend_fd
                         +-- async FD再作成                   +-- 新しいeventfd/pipe
                         +-- signal pipe再作成                +-- 新しいsignal pipe
                         +-- ウォッチャー再登録               +-- events=0で再キュー
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | uv_loop_fork()のAPI宣言 |
| loop.c | `src/unix/loop.c` | ソース | uv_loop_fork()の実装 |
| kqueue.c | `src/unix/kqueue.c` | ソース | macOS/BSDのuv__io_fork()実装 |
| linux.c | `src/unix/linux.c` | ソース | Linuxのuv__io_fork()実装 |
| async.c | `src/unix/async.c` | ソース | uv__async_fork()の実装 |
| signal.c | `src/unix/signal.c` | ソース | uv__signal_loop_fork()の実装 |
