# 通知設計書 23-Interop.Sys.INotify (IN_IGNORED)

## 概要

本ドキュメントは、Linux inotifyサブシステムにおけるIN_IGNORED通知イベントの設計仕様を定義する。IN_IGNOREDは、inotify監視が削除された際にカーネルから発生する通知であり、監視対象ディレクトリの削除、明示的な監視解除、またはinotifyインスタンスのクローズ時に発生する。

### 本通知の処理概要

IN_IGNORED通知は、特定の監視ディスクリプタ（wd）に関連付けられた監視が無効になったことを示す通知である。この通知により、アプリケーションは監視リソースの適切なクリーンアップを実行できる。

**業務上の目的・背景**：ファイルシステム監視において、監視対象のディレクトリが削除されたり、アプリケーションが明示的に監視を解除した場合、関連するリソース（メモリ、ファイルディスクリプタ、内部データ構造）を適切に解放する必要がある。IN_IGNOREDはこのクリーンアップの契機を提供し、リソースリークを防止する。

**通知の送信タイミング**：以下のいずれかの状況で発生する：
1. inotify_rm_watchシステムコールで明示的に監視を解除した場合
2. 監視対象ディレクトリが削除された場合（unlinkやrmdir）
3. 監視対象ディレクトリを含むファイルシステムがアンマウントされた場合
4. inotifyファイルディスクリプタがクローズされた場合

**通知の受信者**：対象の監視ディスクリプタを持つinotifyインスタンスを所有するプロセス。.NETランタイムでは、FileSystemWatcherがこの通知を受信し、内部のWatchedDirectoryオブジェクトをクリーンアップする。

**通知内容の概要**：削除された監視のwd（監視ディスクリプタ）、IN_IGNOREDマスク（0x00008000）が含まれる。名前フィールドは空である。

**期待されるアクション**：受信者は対応する監視ディスクリプタに関連するリソースを解放する。.NETのFileSystemWatcherはWatchedDirectoryをRemoveWatchedDirectory経由で削除する。

## 通知種別

システム通知（カーネル監視状態変更イベント）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（カーネルからユーザー空間への状態変更通知） |
| 優先度 | 中（リソース管理用の通知） |
| リトライ | 無（一度発生した監視削除は取り消せない） |

### 送信先決定ロジック

IN_IGNOREDイベントは、対象の監視ディスクリプタを持つinotifyインスタンスにのみ送信される。複数のプロセスが同一ディレクトリを監視している場合、それぞれが独自のwdを持つため、IN_IGNOREDも個別に発生する。

## 通知テンプレート

### イベント構造体

```c
struct inotify_event {
    int      wd;       // 削除された監視のディスクリプタ
    uint32_t mask;     // IN_IGNORED = 0x00008000
    uint32_t cookie;   // 0（未使用）
    uint32_t len;      // 0（名前なし）
    char     name[];   // 空（名前フィールドなし）
};
```

### 本文テンプレート

```
イベント: IN_IGNORED
監視ディスクリプタ: {wd}
監視が削除されました。
```

### 添付ファイル

なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| wd | 削除された監視ディスクリプタ | inotify_add_watchの戻り値 | Yes |
| mask | イベントマスク（IN_IGNORED） | カーネル設定値 | Yes |
| cookie | イベント関連付けID（常に0） | カーネル設定値 | Yes |
| len | 名前の長さ（常に0） | カーネル設定値 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| システムコール | inotify_rm_watch() | 明示的な監視解除 | アプリケーションが監視を解除 |
| ファイルシステム操作 | rmdir()/unlink() | 監視対象ディレクトリの削除 | ディレクトリ自体が削除された場合 |
| ファイルシステム操作 | umount | 監視対象のアンマウント | ファイルシステムのアンマウント |
| システムコール | close() | inotifyファイルディスクリプタのクローズ | インスタンス終了時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| IN_ONESHOT設定時 | 最初のイベント後に自動的にIN_IGNOREDが発生するが、通常の動作 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[監視削除トリガー] --> B{削除理由}
    B -->|inotify_rm_watch| C[明示的解除]
    B -->|ディレクトリ削除| D[カーネル自動解除]
    B -->|アンマウント| E[カーネル自動解除]
    C --> F[IN_IGNOREDイベント生成]
    D --> F
    E --> F
    F --> G[イベントキューに追加]
    G --> H[read()でイベント取得]
    H --> I[FileSystemWatcher.ProcessEvent]
    I --> J[IN_IGNORED検出]
    J --> K[RemoveWatchedDirectory呼び出し]
    K --> L[WatchedDirectoryクリーンアップ]
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（カーネルレベルの通知機構であり、データベースは使用しない）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 無効なwd | 既に削除されたwdに対するIN_IGNORED | 無視（正常動作） |
| リソースリーク | IN_IGNOREDが処理されない場合 | タイムアウトによるクリーンアップ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（カーネルイベントはリトライ不可） |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 制限なし | IN_IGNOREDは監視削除時に1回のみ発生 |

### 配信時間帯

制限なし（リアルタイム配信）

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

- IN_IGNOREDはリソースクリーンアップのための通知であり、機密情報は含まない
- 監視対象ディレクトリが削除された場合、それ以降のイベントは受信できない

## 備考

- IN_IGNOREDはディレクトリイベントとして扱われる（IN_ISDIRフラグの意味）
- .NETのFileSystemWatcherはIN_IGNOREDを内部的に処理し、ユーザーイベントとしては発火しない
- 複数のWatchedDirectoryが同一のwdを共有している場合、IN_IGNOREDは一度だけ発生する

---

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

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

### 推奨読解順序

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

IN_IGNOREDの定義値を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | pal_io.h | `src/native/libs/System.Native/pal_io.h` | 行339: PAL_IN_IGNORED = 0x00008000の定義 |

**読解のコツ**: IN_IGNOREDは監視の終了を示すイベントであり、他のファイルイベント（IN_DELETE等）とは性質が異なる。

#### Step 2: ネイティブ層の検証を理解する

カーネル定数との一致検証とinotify_rm_watchの実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | pal_io.c | `src/native/libs/System.Native/pal_io.c` | 行193: c_static_assert(PAL_IN_IGNORED == IN_IGNORED) |
| 2-2 | pal_io.c | `src/native/libs/System.Native/pal_io.c` | 行1503-1521: SystemNative_INotifyRemoveWatch実装 |

**主要処理フロー**:
- **行193**: 静的アサートでPAL定数とカーネル定数の一致を検証
- **行1509-1515**: inotify_rm_watch呼び出し

#### Step 3: マネージド層でのIN_IGNORED処理を理解する

FileSystemWatcherがIN_IGNOREDを処理する流れを追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FileSystemWatcher.Linux.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs` | 行599: IN_IGNOREDのisDir判定への影響 |
| 3-2 | FileSystemWatcher.Linux.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs` | 行660-664: IN_IGNOREDケースでRemoveWatchedDirectory呼び出し |
| 3-3 | FileSystemWatcher.Linux.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs` | 行345-355: RemoveWatchedDirectory実装 |

**主要処理フロー**:
- **行599**: `(mask & (IN_ISDIR | IN_IGNORED)) != 0` でisDir判定
- **行660**: `(mask & IN_IGNORED) != 0` でIN_IGNORED検出
- **行662**: `RemoveWatchedDirectory(dir, ignoredFd: nextEvent.wd)` で監視削除
- **行663**: `continue` で他の処理をスキップ

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

```
[カーネル/アプリケーション] 監視削除トリガー
    |
    ├─ inotify_rm_watch (pal_io.c:1503)
    |      |
    |      └─ カーネルがIN_IGNOREDを生成
    |
    └─ ディレクトリ削除/アンマウント
           |
           └─ カーネルがIN_IGNOREDを生成
                  |
                  v
           ProcessEvent (行516)
                  |
                  ├─ isDir判定 (行599)
                  |   └─ IN_IGNOREDはディレクトリイベントとして扱う
                  |
                  └─ (mask & IN_IGNORED) != 0 判定 (行660)
                         |
                         └─ RemoveWatchedDirectory (行662)
                                |
                                v
                         RemoveWatchedDirectoryFromParentAndWatches (行414)
                                |
                                └─ Watch.Watchers.Remove (行466)
```

### データフロー図

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

inotify_rm_watch      ───▶  カーネル監視削除           ───▶  IN_IGNOREDイベント
または
ディレクトリ削除
    |                                                            |
    v                                                            v
inotify_event         ───▶  ProcessEvent()              ───▶  IN_IGNORED検出
(wd, IN_IGNORED)            (行660判定)                         |
                                                                 v
                                                          RemoveWatchedDirectory
                                                                 |
                                                                 v
                                                          _wdToWatch.TryRemove
                                                                 |
                                                                 v
                                                          Watch.Watchers更新
                                                                 |
                                                                 v
                                                          リソース解放完了
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| pal_io.h | `src/native/libs/System.Native/pal_io.h` | ヘッダ | PAL_IN_IGNORED定義（行339） |
| pal_io.c | `src/native/libs/System.Native/pal_io.c` | ソース | 静的アサート（行193）、INotifyRemoveWatch（行1503-1521） |
| FileSystemWatcher.Linux.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs` | ソース | IN_IGNORED処理（行599, 660-664）、RemoveWatchedDirectory（行345-355） |
