# 機能設計書 18-child_process

## 概要

本ドキュメントは、Node.jsのchild_processモジュール（子プロセス生成・管理機能）の機能設計を記述したものである。

### 本機能の処理概要

child_process機能は、Node.jsプロセスから外部コマンドや別のNode.jsプロセスを生成・実行・管理するためのAPIを提供する。非同期/同期の両方のプロセス生成をサポートし、標準入出力のパイプやIPC（プロセス間通信）を通じた親子プロセス間のデータ交換を実現する。

**業務上の目的・背景**：シェルコマンドの実行、外部プログラムの呼び出し、マルチプロセス処理、Node.jsワーカープロセスの生成など、単一プロセスでは実現できない処理を行うために必要である。

**機能の利用シーン**：
- シェルコマンド・スクリプトの実行
- 外部実行ファイルの呼び出し
- Node.jsワーカープロセスの生成（fork）
- CPU集約的な処理の並列実行
- サードパーティツールとの連携
- バックグラウンドタスクの実行

**主要な処理内容**：
1. 非同期プロセス生成（spawn、exec、execFile、fork）
2. 同期プロセス生成（spawnSync、execSync、execFileSync）
3. 標準入出力（stdin、stdout、stderr）の管理
4. IPC（プロセス間通信）チャネルの管理
5. シグナル送信・プロセス終了
6. ハンドル（ソケット、サーバー）の送受信

**関連システム・外部連携**：
- net: ソケットハンドルの送受信
- dgram: UDPソケットハンドルの送受信
- cluster: マルチプロセス実行（内部でforkを使用）
- worker_threads: スレッドベースの並列処理（代替手段）

**権限による制御**：Permission Modelが有効な場合、フラグが子プロセスに継承される。

## 関連画面

本機能はCLI/APIレベルの機能であり、直接関連する画面はない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | - |

## 機能種別

プロセス生成 / プロセス間通信 / コマンド実行

## 入力仕様

### 入力パラメータ

#### spawn(file[, args][, options])

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| file | string | Yes | 実行ファイルパス | 空文字列不可 |
| args | string[] | No | コマンドライン引数 | 配列 |
| options.cwd | string/URL | No | 作業ディレクトリ | 有効なパス |
| options.env | Object | No | 環境変数 | オブジェクト |
| options.detached | boolean | No | 親から切り離し | デフォルトfalse |
| options.stdio | Array/string | No | 標準入出力設定 | 'pipe'/'ignore'/'inherit' |
| options.shell | boolean/string | No | シェル経由実行 | シェルパス指定可 |
| options.timeout | number | No | タイムアウト（ms） | 0以上の整数 |
| options.killSignal | string/number | No | タイムアウト時シグナル | デフォルト'SIGTERM' |
| options.signal | AbortSignal | No | 中断シグナル | AbortSignal |

#### fork(modulePath[, args][, options])

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| modulePath | string/URL | Yes | 実行モジュールパス | 有効なパス |
| args | string[] | No | スクリプト引数 | 配列 |
| options.execPath | string | No | Node.js実行パス | デフォルトprocess.execPath |
| options.execArgv | string[] | No | Node.js引数 | デフォルトprocess.execArgv |
| options.silent | boolean | No | stdio非継承 | デフォルトfalse |
| options.serialization | string | No | シリアライズ方式 | 'json'/'advanced' |

#### exec(command[, options][, callback])

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| command | string | Yes | シェルコマンド | 文字列 |
| options.encoding | string | No | 出力エンコーディング | デフォルト'utf8' |
| options.maxBuffer | number | No | 最大バッファサイズ | デフォルト1MB |
| options.timeout | number | No | タイムアウト（ms） | 0以上 |

#### execFile(file[, args][, options][, callback])

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| file | string | Yes | 実行ファイル | 文字列 |
| args | string[] | No | 引数 | 配列 |
| options | Object | No | オプション | execと同様 |

### 入力データソース

- ファイルシステム（実行ファイル）
- 環境変数
- 標準入力（stdin）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ChildProcess | EventEmitter | 子プロセスオブジェクト |
| ChildProcess.pid | number | プロセスID |
| ChildProcess.stdin | Writable | 標準入力ストリーム |
| ChildProcess.stdout | Readable | 標準出力ストリーム |
| ChildProcess.stderr | Readable | 標準エラーストリーム |
| ChildProcess.exitCode | number | 終了コード |
| ChildProcess.signalCode | string | 終了シグナル |

### 同期関数の戻り値

| 項目名 | 型 | 説明 |
|--------|-----|------|
| pid | number | プロセスID |
| output | Array | 出力配列[stdin, stdout, stderr] |
| stdout | Buffer/string | 標準出力 |
| stderr | Buffer/string | 標準エラー出力 |
| status | number | 終了コード |
| signal | string | 終了シグナル |
| error | Error | エラーオブジェクト |

### 出力先

- アプリケーションコード（戻り値、イベント、コールバック）
- 標準出力/エラー出力（inheritの場合）

## 処理フロー

### 処理シーケンス

```
1. spawn()呼び出し
   └─ normalizeSpawnArguments()で引数正規化
   └─ オプション検証（timeout、signal等）
2. ChildProcessインスタンス生成
   └─ Process（ネイティブ）ハンドル作成
   └─ spawn()でプロセス起動
3. stdio設定
   └─ getValidStdio()でstdio配列変換
   └─ パイプ作成・ソケット割り当て
4. IPC設定（fork時）
   └─ setupChannel()でIPCチャネル初期化
   └─ send()/on('message')の有効化
5. イベント処理
   └─ 'spawn', 'exit', 'close', 'error'イベント発火
```

### フローチャート

```mermaid
flowchart TD
    A[spawn/fork/exec呼び出し] --> B[引数正規化]
    B --> C[ChildProcess生成]
    C --> D[Process.spawn]
    D --> E{エラー?}
    E -->|Yes| F[errorイベント発火]
    E -->|No| G[spawnイベント発火]
    G --> H[stdio設定]
    H --> I{IPC有効?}
    I -->|Yes| J[setupChannel]
    I -->|No| K[プロセス実行中]
    J --> K
    K --> L{終了?}
    L -->|No| K
    L -->|Yes| M[exitイベント発火]
    M --> N[closeイベント発火]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | maxBuffer制限 | デフォルト1MB、超過でERR_CHILD_PROCESS_STDIO_MAXBUFFER | exec/execFile |
| BR-002 | shell警告 | shell:trueでargs使用時DEP0190警告 | spawn with shell |
| BR-003 | IPC必須 | fork()はIPCチャネル必須 | fork |
| BR-004 | シリアライズ | IPCは'json'または'advanced'モード | IPC通信 |
| BR-005 | ハンドル送信 | ソケット/サーバーのみ送信可能 | send()でハンドル |

### 計算ロジック

#### stdio配列変換
```javascript
function stdioStringToArray(stdio, channel) {
  const options = [];
  switch (stdio) {
    case 'ignore':
    case 'overlapped':
    case 'pipe': options.push(stdio, stdio, stdio); break;
    case 'inherit': options.push(0, 1, 2); break;
  }
  if (channel) options.push(channel);
  return options;
}
```

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

本機能はデータベースを直接操作しない。

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | - |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ERR_CHILD_PROCESS_IPC_REQUIRED | Error | fork()でIPCなし | stdio配列に'ipc'を含める |
| ERR_CHILD_PROCESS_STDIO_MAXBUFFER | RangeError | maxBuffer超過 | maxBufferを増やす |
| ERR_INVALID_ARG_TYPE | TypeError | 引数型不正 | 正しい型を使用 |
| ERR_INVALID_ARG_VALUE | TypeError | 引数値不正 | 正しい値を使用 |
| ERR_IPC_CHANNEL_CLOSED | Error | 閉じたチャネルへ送信 | 接続状態を確認 |
| ERR_IPC_DISCONNECTED | Error | 切断後のdisconnect | 接続状態を確認 |
| ERR_IPC_ONE_PIPE | Error | 複数IPCパイプ | IPCは1つのみ |
| ERR_IPC_SYNC_FORK | Error | 同期forkでIPC | 非同期forkを使用 |
| ERR_INVALID_HANDLE_TYPE | Error | 不正ハンドル送信 | サポートハンドルを使用 |
| ErrnoException | Error | OS APIエラー | エラー内容を確認 |

### リトライ仕様

- ハンドル送信失敗時、MAX_HANDLE_RETRANSMISSIONS（3回）まで再送

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

本機能にトランザクション仕様はない。

## パフォーマンス要件

- プロセス生成はOSのfork/execコストがかかる
- 同期関数はイベントループをブロック
- maxBufferを超えると子プロセスが強制終了
- IPCはシリアライズコストが発生（advancedモードの方が効率的）

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

- shell: trueでコマンドインジェクションリスク（DEP0190警告）
- 環境変数に機密情報を含めると子プロセスに継承される
- Permission Model有効時はフラグが継承される
- ユーザー入力をコマンドに含める場合は適切なサニタイズが必要

## 備考

- exec/execFileはutil.promisify対応
- diagnostics_channel 'child_process'でプロセス生成を監視可能
- ChildProcessはSymbolDisposeを実装（using構文対応）
- Windowsではcmd.exeが使用される（shell: true時）

---

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

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

### 推奨読解順序

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

ChildProcessクラスの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | internal/child_process.js | `lib/internal/child_process.js` | ChildProcessクラス（254-311行目） |

**読解のコツ**: ChildProcessはEventEmitterを継承し、Process（ネイティブ）ハンドルをラップしている。

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

各関数の入り口と引数正規化を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | child_process.js | `lib/child_process.js` | module.exports（1044-1054行目） |
| 2-2 | child_process.js | `lib/child_process.js` | normalizeSpawnArguments（567-752行目） |

**主要処理フロー**:
- **125-175行目**: fork() - Node.jsプロセス生成
- **234-239行目**: exec() - シェルコマンド実行
- **326-525行目**: execFile() - ファイル実行
- **788-834行目**: spawn() - 汎用プロセス生成
- **866-912行目**: spawnSync() - 同期プロセス生成

#### Step 3: プロセス生成を理解する

ChildProcess.spawn()の内部処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | internal/child_process.js | `lib/internal/child_process.js` | ChildProcess.prototype.spawn（354-479行目） |
| 3-2 | internal/child_process.js | `lib/internal/child_process.js` | getValidStdio（967-1066行目） |

**主要処理フロー**:
- **354-366行目**: stdioオプション処理
- **395-423行目**: ネイティブspawn呼び出し・エラー処理
- **427-473行目**: stdioストリーム設定

#### Step 4: IPC（プロセス間通信）を理解する

setupChannel()とメッセージ送受信を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | internal/child_process.js | `lib/internal/child_process.js` | setupChannel（578-953行目） |
| 4-2 | internal/child_process.js | `lib/internal/child_process.js` | handleConversion（90-235行目） |

**主要処理フロー**:
- **720-744行目**: send()メソッド
- **746-871行目**: _send()内部実装
- **884-898行目**: disconnect()メソッド

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

```
child_process (lib/child_process.js)
    |
    +-- fork(modulePath, args, options)
    |       +-- normalizeSpawnArguments()
    |       +-- spawn() (with IPC)
    |
    +-- exec(command, options, callback)
    |       +-- normalizeExecArgs()
    |       +-- execFile()
    |
    +-- execFile(file, args, options, callback)
    |       +-- normalizeExecFileArgs()
    |       +-- spawn()
    |       +-- stdout/stderr収集
    |       +-- コールバック呼び出し
    |
    +-- spawn(file, args, options)
    |       +-- normalizeSpawnArguments()
    |       +-- new ChildProcess()
    |       +-- ChildProcess.spawn()
    |             +-- getValidStdio()
    |             +-- this._handle.spawn() [native]
    |             +-- setupChannel() (IPC時)
    |
    +-- spawnSync(file, args, options)
    |       +-- normalizeSpawnArguments()
    |       +-- spawn_sync.spawn() [native]
    |
    +-- execSync(command, options)
    |       +-- normalizeExecArgs()
    |       +-- spawnSync()
    |
    +-- execFileSync(file, args, options)
            +-- normalizeExecFileArgs()
            +-- spawnSync()

internal/child_process (lib/internal/child_process.js)
    |
    +-- ChildProcess
    |       +-- constructor()
    |       |       +-- new Process() [native]
    |       |       +-- onexit handler
    |       +-- spawn(options)
    |       |       +-- getValidStdio()
    |       |       +-- _handle.spawn() [native]
    |       |       +-- setupChannel() (IPC)
    |       +-- kill(sig)
    |       +-- ref() / unref()
    |       +-- [SymbolDispose]()
    |
    +-- setupChannel(target, channel, mode)
    |       +-- Control class
    |       +-- send() / _send()
    |       +-- disconnect() / _disconnect()
    |       +-- handleConversion
    |
    +-- getValidStdio(stdio, sync)
    |       +-- stdioStringToArray()
    |       +-- Pipe作成
    |
    +-- spawnSync(options)
            +-- spawn_sync.spawn() [native]
```

### データフロー図

```
[親プロセス]                              [子プロセス]

spawn/fork/exec
      |
      v
ChildProcess生成 ----------------------> Process起動
      |                                       |
      v                                       v
stdio設定                                 stdin受信
      |                                       |
      +--stdin(Writable)---------------> [入力]
      |                                       |
      +--stdout(Readable)<-------------- [出力]
      |                                       |
      +--stderr(Readable)<-------------- [エラー出力]
      |
      |                    IPC Channel
      |                    (fork時)
      +--send(msg,handle)--------------> on('message')
      +--on('message')<----------------- send(msg,handle)
      |
      |                    ハンドル転送
      +--send(socket)-------------------> 受信ソケット
      +--send(server)-------------------> 受信サーバー
      |
      v
on('exit') <---------------------------- process.exit()
      |
      v
on('close')
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| child_process.js | `lib/child_process.js` | ソース | 公開API（fork、spawn、exec等） |
| internal/child_process.js | `lib/internal/child_process.js` | ソース | ChildProcessクラス、IPC実装 |
| internal/child_process/serialization.js | `lib/internal/child_process/serialization.js` | ソース | IPCシリアライズ |
| internal/validators.js | `lib/internal/validators.js` | ソース | パラメータ検証 |
| internal/errors.js | `lib/internal/errors.js` | ソース | エラーコード定義 |
| internal/socket_list.js | `lib/internal/socket_list.js` | ソース | ソケットリスト管理 |
| src/process_wrap.cc | `src/process_wrap.cc` | C++ソース | ネイティブProcess実装 |
| src/spawn_sync.cc | `src/spawn_sync.cc` | C++ソース | 同期spawn実装 |
