# 機能設計書 162-標準入出力継承無効化

## 概要

本ドキュメントは、libuv の `uv_disable_stdio_inheritance()` APIにより、子プロセスへの標準入出力ファイルディスクリプタの継承を無効化する機能について記述する。

### 本機能の処理概要

本機能は、子プロセスがfork/exec時に親プロセスのファイルディスクリプタを不要に継承することを防止する。

**業務上の目的・背景**：Unixシステムでは、fork()で生成された子プロセスは親プロセスの全ファイルディスクリプタを継承する。サーバーアプリケーション等では、リスニングソケットやパイプなどのFDが子プロセスに漏洩すると、ポートの解放ができなくなるなどの問題が発生する。本機能は、FDにCLOEXECフラグを設定することで、exec時にFDが自動的にクローズされるようにする。

**機能の利用シーン**：サーバーアプリケーションの起動時（uv_run()前）に呼び出し、子プロセスへのFD漏洩を防止する。Node.jsのような子プロセスを頻繁にspawnするアプリケーションで特に重要。

**主要な処理内容**：
1. ファイルディスクリプタ0番から順にCLOEXECフラグを設定する
2. 最初の16個のFDは無条件にCLOEXEC設定を試行する
3. 16番以降はCLOEXEC設定が失敗した時点で走査を終了する

**関連システム・外部連携**：POSIXの`fcntl()`システムコール（F_SETFDによるFD_CLOEXEC設定）を使用する。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 16 | プロセス | 補助機能 | uv_disable_stdio_inheritance()による子プロセスへのFD継承無効化のAPI定義 |
| 29 | その他ユーティリティ | 主機能 | uv_disable_stdio_inheritance()による子プロセスFD継承無効化のAPI定義 |

## 機能種別

システム制御

## 入力仕様

### 入力パラメータ

本関数はパラメータを取らない（void関数）。

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| (なし) | void | - | 引数なし | - |

### 入力データソース

なし

## 出力仕様

### 出力データ

本関数は戻り値を返さない（void関数）。

| 項目名 | 型 | 説明 |
|--------|-----|------|
| (なし) | void | 戻り値なし |

### 出力先

OSカーネルのFDテーブルに対するCLOEXECフラグの設定（副作用）

## 処理フロー

### 処理シーケンス

```
1. fdを0から順にインクリメントしながらループ
   └─ 各fdに対してuv__cloexec(fd, 1)でCLOEXECを設定
2. uv__cloexec()が失敗した場合
   └─ fd > 15 であればループを終了
   └─ fd <= 15 であれば無視して次のfdへ（最初の16個は無条件で試行）
```

### フローチャート

```mermaid
flowchart TD
    A[開始 fd=0] --> B[uv__cloexec fd, 1]
    B --> C{設定成功?}
    C -->|Yes| D[fd++]
    C -->|No| E{fd > 15?}
    E -->|Yes| F[ループ終了]
    E -->|No| D
    D --> B
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 最初16個無条件試行 | FD 0-15は常にCLOEXEC設定を試みる（エラー無視） | 常時 |
| BR-02 | 16番以降はエラーで終了 | FD 16以降でCLOEXEC設定が失敗した場合、走査を打ち切る | fd > 15 |

### 計算ロジック

該当なし

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

該当なし（データベースは使用しない）

## エラー処理

### エラーケース一覧

本関数はvoid関数であり、エラーを報告しない。内部的にFDへのCLOEXEC設定が失敗する可能性があるが、以下の方針で処理する：

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| (内部) | EBADF | 存在しないFD番号へのアクセス | fd <= 15は無視、fd > 15で走査終了 |

### リトライ仕様

リトライは行わない。

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

該当なし

## パフォーマンス要件

起動時に一度だけ呼び出される想定のため、特段のパフォーマンス要件はない。最大でもオープン中のFD数分のfcntl()呼び出しが行われる。

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

- 本機能はセキュリティ向上のために存在する（FD漏洩防止）
- `uv_run()` の前に呼び出すことが推奨される
- 全てのオープンFDに対してCLOEXECを設定するため、意図的に子プロセスに渡したいFDがある場合は注意が必要

## 備考

- Unix実装では `uv__cloexec()` マクロ（内部的にはfcntl()ベース）を使用
- Windows実装では `src/win/process-stdio.c` に別の実装がある（HANDLEのINHERIT属性制御）
- Node.jsでは起動時に自動的にこの関数を呼び出している

---

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

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

### 推奨読解順序

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

本機能固有のデータ構造は特にない。ファイルディスクリプタ番号（int）を使ってOSのFDフラグを操作する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | L1840: uv_disable_stdio_inheritance()のAPI宣言 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | core.c | `src/unix/core.c` | L800-809: Unix実装の全体 |

**主要処理フロー**:
1. **800行目**: 関数定義（void、引数なし）
2. **806行目**: fd=0から無限ループ開始
3. **807行目**: `uv__cloexec(fd, 1)` でCLOEXEC設定、失敗かつ fd > 15 でbreak

**読解のコツ**: `uv__cloexec()` はマクロであり、`src/unix/internal.h` で定義されている。内部的には `fcntl(fd, F_SETFD, FD_CLOEXEC)` 相当の処理を行う。戻り値が非0の場合にエラーを意味する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | process-stdio.c | `src/win/process-stdio.c` | Windows固有の実装（HANDLEの継承属性制御） |

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

```
uv_disable_stdio_inheritance() [src/unix/core.c:800]
    |
    +-- for (fd = 0; ; fd++)
           |
           +-- uv__cloexec(fd, 1) [src/unix/internal.h - マクロ]
                  |
                  +-- fcntl(fd, F_SETFD, FD_CLOEXEC) [POSIX]
```

### データフロー図

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

(なし)         ───> FD 0~N に対して              ───> 各FDのCLOEXECフラグが設定される
                    uv__cloexec(fd, 1) を呼び出し
                    fd > 15 && 失敗 でループ終了
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダー | API宣言（L1840） |
| core.c | `src/unix/core.c` | ソース | Unix実装（L800-809） |
| internal.h | `src/unix/internal.h` | ヘッダー | uv__cloexec()マクロ定義 |
| process-stdio.c | `src/win/process-stdio.c` | ソース | Windows実装 |
