# 機能設計書 113-FSリクエストクリーンアップ

## 概要

本ドキュメントは、libuvのファイルシステムリクエストリソース解放機能 `uv_fs_req_cleanup()` の設計仕様を記述する。非同期FSリクエスト完了後のメモリ解放処理について定義する。

### 本機能の処理概要

`uv_fs_req_cleanup()` は、ファイルシステムリクエスト（uv_fs_t）が完了した後に、リクエストが内部的に確保したメモリリソースを解放する機能である。非同期リクエストではパス文字列やバッファが複製されるため、使用後に必ず本関数を呼び出してメモリリークを防止する必要がある。

**業務上の目的・背景**：libuvのファイルシステム操作は非同期実行時にパス文字列やバッファ領域のコピーを内部で作成する。これらのリソースは自動的には解放されないため、アプリケーションが明示的にクリーンアップを行う必要がある。メモリリーク防止のためのリソース管理基盤として不可欠な機能である。

**機能の利用シーン**：すべてのuv_fs_*操作の完了後コールバック内で呼び出す。特に非同期モードで実行されたFS操作の後に必須。同期モードでもMKDTEMP/MKSTEMPの場合は必要。

**主要な処理内容**：
1. reqのNULLチェック
2. pathおよびnew_pathの解放（非同期リクエスト、MKDTEMP/MKSTEMP時）
3. READDIR結果のクリーンアップ
4. SCANDIR結果のクリーンアップ
5. 動的に確保されたバッファ(bufs)の解放
6. ptr（結果データポインタ）の解放

**関連システム・外部連携**：libuvのメモリ管理機構（uv__free）と連携。カスタムアロケータが設定されている場合はそのfree関数が使用される。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 24 | ファイルシステム操作 | 主機能 | uv_fs_req_cleanup()によるFSリクエストリソース解放のAPI定義 |
| 34 | ファイルシステム | 補助機能 | uv_fs_req_cleanup()の使用パターンの説明 |

## 機能種別

リソース管理処理（メモリ解放・クリーンアップ）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| req | uv_fs_t* | No | ファイルシステムリクエスト | NULLの場合は何もしない |

### 入力データソース

ユーザーが以前に実行したuv_fs_*操作のリクエスト構造体。

## 出力仕様

### 出力データ

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

### 出力先

なし。リクエスト構造体の内部フィールドがNULLにリセットされる。

## 処理フロー

### 処理シーケンス

```
1. NULLチェック
   └─ req == NULLなら即座にreturn
2. path/new_pathの解放
   └─ 条件: pathがNULLでない かつ（cb != NULL または fs_type == MKDTEMP/MKSTEMP）
   └─ pathとnew_pathは同一メモリブロックを共有するため、pathの解放で両方解放される
3. READDIR結果のクリーンアップ
   └─ fs_type == UV_FS_READDIR かつ ptr != NULLの場合
4. SCANDIR結果のクリーンアップ
   └─ fs_type == UV_FS_SCANDIR かつ ptr != NULLの場合
5. バッファの解放
   └─ bufsがbufsml（スタック上の小バッファ）と異なる場合のみ解放
6. ptrの解放
   └─ fs_type != UV_FS_OPENDIR かつ ptr != &req->statbufの場合のみ解放
7. フィールドのNULLリセット
   └─ path, new_path, bufs, ptrをNULLに設定
```

### フローチャート

```mermaid
flowchart TD
    A[uv_fs_req_cleanup 呼び出し] --> B{req == NULL?}
    B -->|Yes| C[return]
    B -->|No| D{path != NULL かつ 非同期 or MKDTEMP/MKSTEMP?}
    D -->|Yes| E[uv__free path]
    D -->|No| F[skip]
    E --> G[path = NULL, new_path = NULL]
    F --> G
    G --> H{READDIR かつ ptr != NULL?}
    H -->|Yes| I[uv__fs_readdir_cleanup]
    H -->|No| J{SCANDIR かつ ptr != NULL?}
    I --> J
    J -->|Yes| K[uv__fs_scandir_cleanup]
    J -->|No| L{bufs != bufsml?}
    K --> L
    L -->|Yes| M[uv__free bufs]
    L -->|No| N[bufs = NULL]
    M --> N
    N --> O{OPENDIR でない かつ ptr != statbuf?}
    O -->|Yes| P[uv__free ptr]
    O -->|No| Q[ptr = NULL]
    P --> Q
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-113-1 | 非同期パス解放 | 非同期リクエスト（cb != NULL）のパスは内部複製されているため解放が必要 | 非同期リクエスト完了時 |
| BR-113-2 | 同期パス保持 | 同期リクエスト（cb == NULL）のパスはユーザー所有メモリを参照しているため解放しない | 同期リクエスト完了時 |
| BR-113-3 | MKDTEMP/MKSTEMP例外 | MKDTEMP/MKSTEMPは同期でも常にメモリを確保するため解放が必要 | MKDTEMP/MKSTEMP操作時 |
| BR-113-4 | path/new_pathメモリ共有 | pathとnew_pathは同一メモリブロックを共有。pathの解放で両方解放される | PATH2マクロ使用の操作 |

### 計算ロジック

特になし。

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

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| (なし) | - | reqがNULLの場合は何もしない | - |

### リトライ仕様

該当なし。エラーは発生しない。

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

該当なし。

## パフォーマンス要件

- メモリ解放操作のため、高速に完了する
- 不要な解放をスキップする最適化が実装されている（bufsml/statbufのチェック）

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

- 解放後のポインタはNULLに設定されるため、Use-After-Free防止に寄与する
- 二重解放（double-free）は発生しない設計

## 備考

- すべてのuv_fs_*コールバック内でuv_fs_req_cleanup()を呼び出すことが推奨される
- fs-poll.cのpoll_cbでも内部的に使用されている（src/fs-poll.c L221）
- uv_fs_copyfileの内部でも中間リクエストのクリーンアップに使用される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | **L1449-1460**: uv_fs_s構造体。path, ptr, bufs, statbuf等のリソースフィールド |
| 1-2 | uv.h | `include/uv.h` | **L1469**: uv_fs_req_cleanup()のAPI宣言 |

**読解のコツ**: uv_fs_tのpathフィールドはconst char*、ptrフィールドはvoid*。これらは操作の種類によって異なるメモリ管理が必要になる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | fs.c | `src/unix/fs.c` | **L2241-2271**: uv_fs_req_cleanup()の実装 |

**主要処理フロー**:
1. **L2242-2243**: reqがNULLなら即座にreturn
2. **L2250-2253**: pathの解放条件判定（非同期 or MKDTEMP/MKSTEMP）
3. **L2255-2256**: path/new_pathをNULLにリセット
4. **L2258-2259**: READDIR結果のクリーンアップ
5. **L2261-2262**: SCANDIR結果のクリーンアップ
6. **L2264-2266**: bufsの解放（bufsmlと異なる場合のみ）
7. **L2268-2270**: ptrの解放（OPENDIR以外かつstatbuf以外）

#### Step 3: メモリ割り当てパターンを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | fs.c | `src/unix/fs.c` | **L106-117**: PATHマクロ。非同期時にuv__strdupでパスを複製 |
| 3-2 | fs.c | `src/unix/fs.c` | **L119-137**: PATH2マクロ。path+new_pathを一括mallocで確保 |

**読解のコツ**: PATH2マクロではpath_len + new_path_lenの一括確保を行い、new_pathはpath + path_lenのオフセットを指す。そのため、uv__free(path)で両方のメモリが解放される。

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

```
uv_fs_req_cleanup()                [src/unix/fs.c L2241]
    |
    +-- uv__free(req->path)        [非同期パスの解放]
    |
    +-- uv__fs_readdir_cleanup()   [READDIR結果の解放]
    |
    +-- uv__fs_scandir_cleanup()   [SCANDIR結果の解放]
    |
    +-- uv__free(req->bufs)        [動的バッファの解放]
    |
    +-- uv__free(req->ptr)         [結果データの解放]
```

### データフロー図

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

uv_fs_t* req    ──> 各フィールドの条件判定   ──> フィールドをNULLにリセット
  .path         ──> 非同期/MKDTEMP時解放     ──> .path = NULL
  .new_path     ──>                          ──> .new_path = NULL
  .bufs         ──> bufsml以外なら解放       ──> .bufs = NULL
  .ptr          ──> statbuf/OPENDIR以外解放  ──> .ptr = NULL
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダー | uv_fs_req_cleanup()のAPI宣言、uv_fs_t構造体定義 |
| fs.c (Unix) | `src/unix/fs.c` | ソース | Unix系のクリーンアップ実装 |
| fs.c (Win) | `src/win/fs.c` | ソース | Windows版のクリーンアップ実装 |
| fs-poll.c | `src/fs-poll.c` | ソース | 内部使用箇所（poll_cb内） |
