# 機能設計書 93-シグナルハンドル初期化

## 概要

本ドキュメントは、libuvにおけるシグナルハンドル初期化機能（uv_signal_init()）の設計を記述する。シグナル監視ハンドルを初期化し、イベントループでのシグナル検知を可能にする。

### 本機能の処理概要

**業務上の目的・背景**：Unixシグナルは非同期イベントの代表例であり、プロセス間通信やOS通知に広く利用される。libuvのシグナルハンドルは、OSのシグナル機構をイベントループベースの非同期パターンに統合する。uv_signal_init()はシグナル監視の前提となるハンドルの初期化を担い、内部でシグナル通知用のパイプとI/Oウォッチャーも初期化する。

**機能の利用シーン**：SIGINT/SIGTERM等によるアプリケーションの正常終了制御、SIGHUP等による設定再読み込み、SIGUSR1/SIGUSR2等によるユーザー定義シグナル処理、子プロセスのSIGCHLD監視などで利用される。

**主要な処理内容**：
1. シグナルループの初期化（signal_pipefdの作成とI/Oウォッチャーの登録、初回のみ）
2. ハンドルの共通フィールド初期化（UV_SIGNALタイプとして登録）
3. シグナル固有フィールドの初期化（signum=0、caught_signals=0、dispatched_signals=0）

**関連システム・外部連携**：OSのパイプ機構、POSIX sigaction()、内部I/Oウォッチャーシステムと連携する。

**権限による制御**：特になし。ハンドル初期化自体に特別な権限は不要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 15 | シグナル | 主機能 | uv_signal_init()によるシグナルハンドル初期化のAPI定義 |

## 機能種別

ハンドル初期化

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| loop | uv_loop_t* | Yes | ハンドルを登録するイベントループ | NULLでないこと、初期化済みであること |
| handle | uv_signal_t* | Yes | 初期化するシグナルハンドル | NULLでないこと |

### 入力データソース

呼び出し元コードから直接パラメータとして渡される。

## 出力仕様

### 出力データ

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

### 出力先

呼び出し元への戻り値として返却。handleの初期化。

## 処理フロー

### 処理シーケンス

```
1. uv__signal_loop_once_init(loop) を呼び出す
   ├─ signal_pipefdが既に初期化済みなら即座に返る
   └─ 未初期化なら:
       ├─ uv__make_pipe()でシグナル用パイプを作成
       └─ uv__io_init_start()でI/Oウォッチャーを登録
2. uv__handle_init()を呼び出す
   └─ ハンドルをUV_SIGNAL型としてループに登録
3. ハンドルの固有フィールドを初期化する
   ├─ handle->signum = 0
   ├─ handle->caught_signals = 0
   └─ handle->dispatched_signals = 0
4. 0を返す
```

### フローチャート

```mermaid
flowchart TD
    A[uv_signal_init 呼び出し] --> B[uv__signal_loop_once_init]
    B --> C{signal_pipefd 初期化済み?}
    C -->|Yes| E[uv__handle_init]
    C -->|No| D[パイプ作成 + I/Oウォッチャー登録]
    D --> D2{成功?}
    D2 -->|Yes| E
    D2 -->|No| F[エラーコード返却]
    E --> G[signum=0, caught_signals=0, dispatched_signals=0]
    G --> H[0を返す]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-93-1 | ループ初期化は一度だけ | signal_pipefdの作成はループごとに初回のみ実行 | 初回のuv_signal_init()呼び出し時 |
| BR-93-2 | NONBLOCKパイプ | シグナルパイプはUV_NONBLOCK_PIPEフラグ付きで作成 | パイプ作成時 |
| BR-93-3 | 初期状態 | signum=0は「未開始」状態を表す | ハンドル初期化後 |

### 計算ロジック

特になし。

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

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_ENOMEM | メモリ不足 | パイプ作成やI/Oウォッチャー登録でメモリ不足 | メモリを確保してリトライ |
| UV_EMFILE | FD上限 | パイプ作成でFDが上限に達した | 不要なFDをクローズ |

### リトライ仕様

リトライは通常不要。リソース制約が原因の場合はリソース解放後にリトライ可能。

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

該当なし。

## パフォーマンス要件

初期化処理は同期的に実行され、通常はマイクロ秒オーダーで完了する。

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

- シグナルパイプのFDはcloexecフラグ付きで作成され、子プロセスへの漏洩を防止する

## 備考

- シグナル処理は「セルフパイプトリック」を使用。シグナルハンドラ内でパイプに書き込み、イベントループ側でパイプから読み取る
- グローバルなRBツリーにより、複数のイベントループからの同一シグナル監視がサポートされる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | **1720-1725行目**: uv_signal_s構造体。signal_cb、signum、プライベートフィールドを確認 |
| 1-2 | signal.c | `src/unix/signal.c` | **35-38行目**: uv__signal_msg_t構造体。シグナルハンドラとイベントループ間の通信メッセージ |

**読解のコツ**: UV_SIGNAL_PRIVATE_FIELDSにはcaught_signals、dispatched_signals、tree_entryが含まれる。RBツリーのエントリがシグナル番号で管理される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | signal.c | `src/unix/signal.c` | **341-354行目**: uv_signal_init()の実装 |

**主要処理フロー**:
1. **344行目**: `uv__signal_loop_once_init(loop)` - ループのシグナルインフラを初期化
2. **348行目**: `uv__handle_init(loop, handle, UV_SIGNAL)` - 共通ハンドル初期化
3. **349-351行目**: signum=0、カウンタ初期化

#### Step 3: ループ初期化処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | signal.c | `src/unix/signal.c` | **260-283行目**: uv__signal_loop_once_init()。パイプ作成とI/Oウォッチャー登録 |

**主要処理フロー**:
- **265-267行目**: signal_pipefd[0]が-1でなければ既に初期化済み
- **269行目**: `uv__make_pipe(pipefd, UV_NONBLOCK_PIPE)` でノンブロッキングパイプ作成
- **273-274行目**: `uv__io_init_start()` でI/Oウォッチャーを登録

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

```
uv_signal_init(loop, handle)
    |
    +-- uv__signal_loop_once_init(loop)
    |       |
    |       +-- uv__make_pipe(pipefd, UV_NONBLOCK_PIPE)
    |       +-- uv__io_init_start(loop, &loop->signal_io_watcher, ...)
    |
    +-- uv__handle_init(loop, handle, UV_SIGNAL)
```

### データフロー図

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

uv_loop_t*       ---> signal_pipefd作成    --->
                      I/Oウォッチャー登録  --->        初期化済みuv_signal_t*
uv_signal_t*     ---> ハンドル初期化       --->        int (0 or error)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | API宣言とuv_signal_t構造体定義 |
| signal.c | `src/unix/signal.c` | ソース | Unix系シグナル処理全体の実装 |
| signal.c | `src/win/signal.c` | ソース | Windowsシグナル処理実装 |
