# 機能設計書 159-プロセスタイトル制御

## 概要

本ドキュメントは、libuvライブラリにおけるuv_setup_args()/uv_get_process_title()/uv_set_process_title()関数によるプロセスタイトル制御機能の設計を記述する。

### 本機能の処理概要

プロセスタイトル（psコマンド等で表示されるプロセス名）の初期化・取得・設定を行うクロスプラットフォームAPIを提供する。uv_setup_args()で初期化し、uv_set_process_title()で変更し、uv_get_process_title()で現在のタイトルを取得する。

**業務上の目的・背景**：サーバーアプリケーションでは、プロセスの状態をps出力に反映させることで運用監視を容易にするニーズがある。例えば「myapp: handling 42 connections」のようにプロセスタイトルを動的に更新することで、運用者がプロセスの状態を一目で把握できる。Unix系OSではargv[0]領域の書き換えによりプロセスタイトルを変更するが、この操作は繊細であり、libuvが安全なラッパーを提供する。

**機能の利用シーン**：サーバープロセスの状態表示（接続数、処理中タスク等）、ワーカープロセスの役割表示、デバッグ時のプロセス識別、運用監視ツールとの連携などに利用される。

**主要な処理内容**：
1. uv_setup_args(): argv領域のサイズ計算と新しいargv配列の確保・コピー
2. uv_set_process_title(): ミューテックスによる排他制御下でargv[0]領域にタイトル文字列を書き込み
3. uv_get_process_title(): ミューテックスによる排他制御下で現在のタイトルをバッファにコピー

**関連システム・外部連携**：
- Unix: argv[0]領域の直接書き換え、prctl(PR_SET_NAME)（Linux）、setproctitle()（BSD）等
- Windows: SetConsoleTitleW() Win32 API

**権限による制御**：特別な権限は不要。一般ユーザー権限で実行可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 29 | その他ユーティリティ | 主機能 | uv_setup_args()/get_process_title()/set_process_title()のAPI定義 |

## 機能種別

制御処理（プロセスタイトルの初期化・取得・設定）

## 入力仕様

### 入力パラメータ

#### uv_setup_args()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| argc | int | Yes | コマンドライン引数の数 | argc <= 0の場合、そのままargvを返す |
| argv | char** | Yes | コマンドライン引数配列 | - |

#### uv_set_process_title()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| title | const char* | Yes | 設定するプロセスタイトル文字列 | - |

#### uv_get_process_title()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| buffer | char* | Yes | タイトルを格納するバッファ | NULLの場合UV_EINVAL |
| size | size_t | Yes | バッファサイズ | 0の場合UV_EINVAL |

### 入力データソース

呼び出し元からの引数。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 (setup_args) | char** | 新しいargv配列（コピーされたもの） |
| buffer (get_process_title) | char* | 現在のプロセスタイトル文字列 |
| 戻り値 (set/get) | int | 成功時0、失敗時負のエラーコード |

### 出力先

uv_setup_args()は新しいargv配列を返す。uv_get_process_title()は呼び出し元バッファに書き込む。

## 処理フロー

### 処理シーケンス

```
1. uv_setup_args(argc, argv):
   ├─ argc <= 0の場合、そのままargvを返す
   ├─ argv[0]のサイズ（pt.len, pt.cap）を計算
   ├─ 全argv文字列の合計サイズとポインタテーブルのサイズを算出
   ├─ uv__malloc()で新しいメモリを確保
   ├─ argv文字列を新しい領域にコピー
   ├─ pt.capにargv配列全体の連続メモリ長を設定
   ├─ args_mem, process_titleを保存
   └─ 新しいargv配列を返す

2. uv_set_process_title(title):
   ├─ args_memがNULL（uv_setup_args未呼び出し）の場合UV_ENOBUFSを返す
   ├─ strlen(title)でタイトル長を計算
   ├─ uv_once()でミューテックスを初期化
   ├─ ミューテックスロック
   ├─ len >= pt.capの場合、pt.cap - 1に切り詰め
   ├─ memcpy()でタイトルをpt.strにコピー
   ├─ memset()で残りをNULクリア
   ├─ uv__set_process_title()でOS固有の処理を実行
   ├─ ミューテックスアンロック
   └─ return 0

3. uv_get_process_title(buffer, size):
   ├─ bufferがNULLまたはsizeが0の場合UV_EINVALを返す
   ├─ args_memがNULLの場合UV_ENOBUFSを返す
   ├─ uv_once()でミューテックスを初期化
   ├─ ミューテックスロック
   ├─ size <= process_title.lenの場合UV_ENOBUFSを返す
   ├─ memcpy()でバッファにコピー
   ├─ NUL終端を設定
   ├─ ミューテックスアンロック
   └─ return 0
```

### フローチャート

```mermaid
flowchart TD
    A[uv_setup_args] --> B{argc <= 0?}
    B -->|Yes| C[return argv]
    B -->|No| D[サイズ計算]
    D --> E[uv__malloc]
    E --> F{malloc成功?}
    F -->|No| G[return argv]
    F -->|Yes| H[argv文字列コピー]
    H --> I[process_title/args_mem保存]
    I --> J[return new_argv]

    K[uv_set_process_title] --> L{args_mem == NULL?}
    L -->|Yes| M[return UV_ENOBUFS]
    L -->|No| N[mutex lock]
    N --> O{len >= cap?}
    O -->|Yes| P[len = cap - 1]
    O -->|No| Q[memcpy title]
    P --> Q
    Q --> R[memset NUL padding]
    R --> S[uv__set_process_title]
    S --> T[mutex unlock]
    T --> U[return 0]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-159-01 | 初期化必須 | uv_setup_args()をuv_set/get_process_title()の前に呼び出す必要がある | 常時 |
| BR-159-02 | タイトル切り詰め | タイトル文字列がargv[0]領域のキャパシティを超える場合、cap-1文字に切り詰める | タイトル長 >= cap |
| BR-159-03 | NULパディング | タイトル設定時、argv[0]領域の未使用部分はNUL文字で埋められる | 常時 |
| BR-159-04 | スレッドセーフ | ミューテックスによる排他制御でスレッドセーフ性を保証 | 常時 |
| BR-159-05 | ワンスガード | ミューテックスの初期化はuv_once()で一度だけ実行 | 初回呼び出し時 |

### 計算ロジック

- argv全体のサイズ: `pt.cap = argv[argc-1] + strlen(argv[argc-1]) + 1 - argv[0]`
- 新しいメモリサイズ: `合計文字列長 + (argc + 1) * sizeof(char*)`

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

該当なし（データベース操作は行わない）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_EINVAL | 引数不正 | buffer==NULL, size==0 | 有効な引数を渡す |
| UV_ENOBUFS | バッファ不足 | uv_setup_args未呼び出し、またはバッファサイズ不足 | uv_setup_argsを先に呼び出す、または十分なバッファを用意 |

### リトライ仕様

リトライは不要。

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

該当なし。

## パフォーマンス要件

軽量な処理。ミューテックスのロック/アンロックのオーバーヘッドはあるが無視できるレベル。

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

プロセスタイトルはps等で他のユーザーからも見える。機密情報（パスワード、トークン等）をプロセスタイトルに含めてはならない。

## 備考

- uv_setup_args()はmain()関数の最初で呼び出すことが推奨される。
- argv[0]領域のキャパシティ（pt.cap）は、元のargv配列全体の連続メモリ領域のサイズとなる。
- Windowsではuv_setup_args()は何もせずargvをそのまま返す。タイトル設定はSetConsoleTitleW()で行われる。
- uv__process_title_cleanup()関数はvalgrindでのメモリリーク検出を避けるためのクリーンアップ関数。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | proctitle.c | `src/unix/proctitle.c` | uv__process_title構造体の定義（27-31行目） |

**読解のコツ**: `struct uv__process_title` はstr（現在のタイトル文字列ポインタ）、len（タイトル長）、cap（最大キャパシティ）の3フィールドで構成される。capはuv_setup_args()で一度だけ計算される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | uv.h | `include/uv.h` | API宣言（1283-1285行目） |

**主要処理フロー**:
1. **1283行目**: `char** uv_setup_args(int argc, char** argv);`
2. **1284行目**: `int uv_get_process_title(char* buffer, size_t size);`
3. **1285行目**: `int uv_set_process_title(const char* title);`

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | proctitle.c | `src/unix/proctitle.c` | プロセスタイトル制御の全実装 |

**主要処理フロー**:
- **27-31行目**: uv__process_title構造体定義
- **35-38行目**: 静的変数（ミューテックス、process_title、args_mem）
- **46-93行目**: `uv_setup_args()` - argvの安全なコピーとcap計算
  - **53-54行目**: argc <= 0のガード
  - **56-58行目**: pt初期化（argv[0]のstr, len, cap）
  - **68-70行目**: uv__malloc()によるメモリ確保
  - **87行目**: `pt.cap = argv[i - 1] + size - argv[0]` でキャパシティ計算
- **96-124行目**: `uv_set_process_title()` - タイトル設定
  - **101-102行目**: args_mem NULLチェック
  - **107-108行目**: ミューテックスによる排他制御
  - **110-114行目**: キャパシティ超過時の切り詰め処理
  - **116行目**: memcpy()でタイトルコピー
  - **117行目**: memset()でNULパディング
  - **119行目**: uv__set_process_title()呼び出し（OS固有処理）
- **127-151行目**: `uv_get_process_title()` - タイトル取得
  - **128-129行目**: 引数バリデーション
  - **132-133行目**: args_mem NULLチェック
  - **138-140行目**: バッファサイズチェック

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | util.c | `src/win/util.c` | Windows版プロセスタイトル制御実装 |

**主要処理フロー**:
- **335-337行目**: `uv_setup_args()` - 何もせずargvを返す
- **344行目以降**: `uv_set_process_title()` - SetConsoleTitleW()使用
- **390行目以降**: `uv_get_process_title()` - 保存されたタイトルを返す

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

```
uv_setup_args(argc, argv)
    +-- uv__malloc(size)            ... 新しいargv配列用メモリ確保
    +-- memcpy()                    ... argv文字列のコピー

uv_set_process_title(title)
    +-- uv_once()                   ... ミューテックス初期化（一度だけ）
    +-- uv_mutex_lock()             ... 排他制御開始
    +-- memcpy() / memset()         ... argv[0]領域への書き込み
    +-- uv__set_process_title()     ... OS固有処理（prctl等）
    +-- uv_mutex_unlock()           ... 排他制御終了

uv_get_process_title(buffer, size)
    +-- uv_once()                   ... ミューテックス初期化（一度だけ）
    +-- uv_mutex_lock()             ... 排他制御開始
    +-- memcpy()                    ... タイトル文字列のコピー
    +-- uv_mutex_unlock()           ... 排他制御終了
```

### データフロー図

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

argc, argv ──────────────> uv_setup_args()            ──> new_argv (コピー済み)
                            +-- argv[0]領域サイズ計算        process_title (内部状態)

title (const char*) ─────> uv_set_process_title()     ──> argv[0]領域 (書き換え済み)
                            +-- mutex排他制御                process_title更新
                            +-- uv__set_process_title()     戻り値: 0 or error

buffer, size ────────────> uv_get_process_title()     ──> buffer (タイトル文字列)
                            +-- mutex排他制御                戻り値: 0 or error
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | API宣言 |
| proctitle.c | `src/unix/proctitle.c` | ソース | Unix汎用プロセスタイトル制御実装 |
| bsd-proctitle.c | `src/unix/bsd-proctitle.c` | ソース | BSD系uv__set_process_title()実装 |
| no-proctitle.c | `src/unix/no-proctitle.c` | ソース | プロセスタイトル非対応環境のnoop実装 |
| os390-proctitle.c | `src/unix/os390-proctitle.c` | ソース | z/OS固有のプロセスタイトル実装 |
| ibmi.c | `src/unix/ibmi.c` | ソース | IBM i固有のプロセスタイトル実装 |
| aix.c | `src/unix/aix.c` | ソース | AIX固有のプロセスタイトル実装 |
| util.c | `src/win/util.c` | ソース | Windows版プロセスタイトル制御実装 |
