# 機能設計書 70-パイプペア作成

## 概要

本ドキュメントは、接続済みパイプのペアを作成する機能（`uv_pipe()`）の設計を記述する。

### 本機能の処理概要

接続済みのパイプペア（読み取り端と書き込み端）を作成する。Unixではpipe2()/pipe()システムコール、WindowsではCreateNamedPipe()+CreateFile()による内部Named Pipeペアとして実装される。

**業務上の目的・背景**：プロセス間通信やスレッド間通知のための軽量な通信チャネルとして、接続済みのパイプペアが必要となる場面は多い。子プロセスの標準入出力リダイレクト、内部シグナリング、イベントループ間の通知などに使用される。

**機能の利用シーン**：子プロセス生成時の標準入出力パイプ作成、スレッドプールからのイベントループへの通知チャネル、libuvの内部実装（uv__make_pipe()経由）での使用など。

**主要な処理内容**：
1. パイプペアの作成（OSのpipe()またはCreateNamedPipe()）
2. CLOEXEC（close-on-exec）フラグの設定
3. ノンブロッキングモードの設定（UV_NONBLOCK_PIPEフラグ指定時）

**関連システム・外部連携**：Unix pipe2()/pipe()、Windows CreateNamedPipe()/CreateFile() API。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 19 | パイプ | 主機能 | uv_pipe()による接続済みパイプペア作成のAPI定義 |

## 機能種別

リソース作成（OSパイプの作成）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| fds | uv_file[2] | Yes | 作成されたパイプのFDを格納する配列。fds[0]が読み取り端、fds[1]が書き込み端 | - |
| read_flags | int | Yes | 読み取り端のフラグ（UV_NONBLOCK_PIPEで非ブロッキング） | - |
| write_flags | int | Yes | 書き込み端のフラグ（UV_NONBLOCK_PIPEで非ブロッキング） | - |

### 入力データソース

呼び出し元アプリケーションから直接提供される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | int | 成功時は0、失敗時は負のエラーコード |
| fds[0] | uv_file | 読み取り端のファイルディスクリプタ |
| fds[1] | uv_file | 書き込み端のファイルディスクリプタ |

### 出力先

fds配列にファイルディスクリプタが格納される。

## 処理フロー

### 処理シーケンス

```
[Unix]
1. pipe2()/pipe()でパイプペア作成
   └─ pipe2()が使えるプラットフォームではO_CLOEXECフラグ付きで作成
   └─ 両方がNONBLOCKの場合はpipe2にUV_FS_O_NONBLOCKも追加
2. CLOEXECフラグ設定（pipe2未使用の場合）
   └─ uv__cloexec(temp[0], 1) と uv__cloexec(temp[1], 1)
3. ノンブロッキングモード設定（要求時）
   └─ read_flags & UV_NONBLOCK_PIPE → uv__nonblock(temp[0], 1)
   └─ write_flags & UV_NONBLOCK_PIPE → uv__nonblock(temp[1], 1)
4. FDの返却
   └─ fds[0] = temp[0], fds[1] = temp[1]

[Windows]
1. フラグ設定
   └─ read_flags |= UV_READABLE_PIPE, write_flags |= UV_WRITABLE_PIPE
2. uv__create_pipe_pair()でNamed Pipeペア作成
3. _open_osfhandle()でCランタイムFDに変換
4. FDの返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始: uv_pipe] --> B{プラットフォーム}
    B -->|Unix| C{pipe2利用可能?}
    C -->|Yes| D[pipe2 with O_CLOEXEC]
    C -->|No| E[pipe + uv__cloexec]
    D --> F{NONBLOCKフラグ?}
    E --> F
    F -->|Yes| G[uv__nonblock 設定]
    F -->|No| H[fds に FD 設定]
    G --> H
    B -->|Windows| I[uv__create_pipe_pair]
    I --> J[_open_osfhandle で FD 変換]
    J --> H
    H --> K[return 0]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | CLOEXEC自動設定 | 作成されたパイプFDには常にCLOEXECが設定される | 全プラットフォーム |
| BR-02 | pipe2最適化 | Linux/FreeBSD/OpenBSD/DragonFly/NetBSD/illumosではpipe2()を使用し、CLOEXECをアトミックに設定する | 対応プラットフォーム |
| BR-03 | 両端NONBLOCK最適化 | 両端ともNONBLOCKの場合、pipe2()にO_NONBLOCKも同時に渡して効率化する | pipe2対応プラットフォーム |
| BR-04 | Windows FD変換 | Windows版ではOSハンドルを_open_osfhandle()でCランタイムFDに変換して返す | Windows環境 |

### 計算ロジック

特になし。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_EMFILE | FD上限到達 | プロセスのFD上限に達した | 不要なFDをクローズ |
| UV_ENFILE | システムFD上限 | システム全体のFD上限に達した | システム設定を確認 |
| UV_UNKNOWN | 不明なエラー | Windows版で_open_osfhandle()が失敗 | - |

### リトライ仕様

UV_EMFILE/UV_ENFILEの場合、FDを解放してからリトライ可能。

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

該当なし。失敗時は作成途中のFD/ハンドルをクローズして元の状態に戻る。

## パフォーマンス要件

OSのpipe()/pipe2()システムコールを含むが、通常はマイクロ秒単位で完了する。

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

- CLOEXECフラグにより、exec()時にFDが子プロセスに継承されることを防止する
- pipe2()未対応プラットフォームでは、CLOEXECの設定に競合のウィンドウが存在する

## 備考

- uv__make_pipe()はuv_pipe()のラッパーであり、両端にUV_NONBLOCK_PIPEを適用する
- libuvの内部実装（シグナルパイプ、非同期通知等）でも使用される
- UV_NONBLOCK_PIPEの値は0x40であり、UV_OVERLAPPED_PIPEと同じ値（互換性のため）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | L513: uv_pipe()の関数宣言 |
| 1-2 | uv.h | `include/uv.h` | L1052: UV_NONBLOCK_PIPE定義（値: 0x40） |

**読解のコツ**: UV_NONBLOCK_PIPEはuv_stdio_flags列挙の一部であるが、uv_pipe()のフラグとしても使用される。

#### Step 2: Unix実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | pipe.c (Unix) | `src/unix/pipe.c` | L497-547: uv_pipe() Unix版実装 |

**主要処理フロー（L497-547）**:
1. **500-506行目**: pipe2()対応プラットフォームの判定（プリプロセッサ条件）
2. **507行目**: `flags = O_CLOEXEC` をベースフラグとして設定
3. **509-510行目**: 両端NONBLOCKの場合、O_NONBLOCKも追加
4. **512-513行目**: `pipe2(temp, flags)` でパイプ作成
5. **515-519行目**: 両端NONBLOCKの場合は即座にFDを返却（追加設定不要）
6. **521-528行目**: pipe2()未対応の場合、pipe()後にuv__cloexec()を個別設定
7. **531-537行目**: 個別のNONBLOCK設定
8. **543-546行目**: 失敗時のクリーンアップ（両端をクローズ）

#### Step 3: Windows実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | pipe.c (Win) | `src/win/pipe.c` | L349-391: uv_pipe() Windows版実装 |
| 3-2 | pipe.c (Win) | `src/win/pipe.c` | L249-346: uv__create_pipe_pair() 内部実装 |

**主要処理フロー（Windows版 L349-391）**:
1. **358-359行目**: UV_READABLE_PIPE/UV_WRITABLE_PIPEフラグを追加
2. **360-365行目**: `uv__create_pipe_pair()` でNamed Pipeペアを作成
3. **368-377行目**: `_open_osfhandle()` で読み取り端のFDを取得
4. **378-387行目**: `_open_osfhandle()` で書き込み端のFDを取得

#### Step 4: 内部ラッパーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | pipe.c (Unix) | `src/unix/pipe.c` | L550-554: uv__make_pipe()。uv_pipe()のラッパー |

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

```
uv_pipe(fds, read_flags, write_flags)
    |
    +-- [Unix]
    |   +-- pipe2(temp, O_CLOEXEC | O_NONBLOCK)  [対応プラットフォーム]
    |   |   or
    |   +-- pipe(temp)                             [非対応プラットフォーム]
    |   |   +-- uv__cloexec(temp[0], 1)
    |   |   +-- uv__cloexec(temp[1], 1)
    |   +-- uv__nonblock(temp[0], 1)              [read_flags指定時]
    |   +-- uv__nonblock(temp[1], 1)              [write_flags指定時]
    |
    +-- [Windows]
        +-- uv__create_pipe_pair(&readh, &writeh, ...)
        |   +-- uv__pipe_server()                  [サーバーパイプ作成]
        |   +-- CreateFileA()                      [クライアントパイプ作成]
        |   +-- ConnectNamedPipe()                 [接続]
        +-- _open_osfhandle(readh)
        +-- _open_osfhandle(writeh)
```

### データフロー図

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

uv_file fds[2] ------------>  uv_pipe() -------> fds[0]: 読み取り端FD
int read_flags                  |                  fds[1]: 書き込み端FD
int write_flags                 +-- pipe2/pipe [Unix]
                                +-- CreateNamedPipe [Win]
                                +-- CLOEXEC設定
                                +-- NONBLOCK設定(任意)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダー | API宣言（L513）、UV_NONBLOCK_PIPE定義（L1052） |
| pipe.c (Unix) | `src/unix/pipe.c` | ソース | Unix版実装（L497-554） |
| pipe.c (Win) | `src/win/pipe.c` | ソース | Windows版実装（L249-391） |
