ShareLockのオーナーシップをIsolatedExecutionStateに統一し、Fiberアイソレーション下の競合状態を修正

rails/rails

ActiveSupport::Concurrency::ShareLockがロックの所有者をThread.currentで識別していたため、:fiberアイソレーション下では同一スレッド上の複数のFiberが同じ所有者として扱われていました。このPRはオーナーシップの識別をActiveSupport::IsolatedExecutionState.contextに切り替えることで、Fiberスケジューラ環境(Falconなど)での定数破壊バグを修正します。

背景

config.active_support.isolation_level = :fiberを設定した環境では、同一スレッド上の複数のリクエストFiberがShareLockから単一の所有者として見えていました。この問題により、リローダーのインターロックが正常に機能しなくなっていました。

具体的には、あるFiberがshareロックを保持している状態でも、別のFiberによる排他的な:unloadロックの取得が許可されてしまいます。その結果、リクエスト処理の途中でオートロードされた定数がクリアされ、ビューで予期しないNoMethodErrorが発生します。この症状はFalconのようなFiberスケジューラを使用するサーバーで、起動後の初回ファイル変更時に顕在化します。

一方、CurrentAttributesやその他のフレームワーク機能は既にActiveSupport::IsolatedExecutionState.contextを「現在の実行コンテキスト」の識別に使用しています。ShareLockだけがThread.currentを使い続けていたことが、この不整合の原因でした。

技術的な変更

ShareLockのオーナーシップ識別をThread.currentからIsolatedExecutionState.contextに変更し、関連する変数名・フィールド名をthread中心の命名からowner中心の命名に統一しました。

activesupport/lib/active_support/concurrency/share_lock.rbでは、@exclusive_thread@exclusive_ownerに改名し、内部でスレッドを管理していた@sleeping@sharing@waitingの各Hashのキーも同様にオーナーオブジェクトとして扱うように変更されています。raw_stateメソッドの返り値も:threadキーが:ownerキーに変更されました。

変更前:

threads = @sleeping.keys | @sharing.keys | @waiting.keys
threads |= [@exclusive_thread] if @exclusive_thread

data[thread] = {
  thread: thread,
  sharing: @sharing[thread],
  exclusive: @exclusive_thread == thread,
  ...
}

変更後:

owners = @sleeping.keys | @sharing.keys | @waiting.keys
owners |= [@exclusive_owner] if @exclusive_owner

data[owner] = {
  owner: owner,
  sharing: @sharing[owner],
  exclusive: @exclusive_owner == owner,
  ...
}

ActionDispatch::DebugLocksraw_stateの唯一の利用者であるため、同様に変数名をthreadからownerに変更しています。加えて、Fiberにはstatusメソッドが存在しないためFiber#statusの呼び出しでクラッシュしていた問題も修正されました。表示メッセージはスレッドとFiber両方に対応する汎用表現に変更されています。

変更前:

msg = +"Thread #{info[:index]} [0x#{thread.__id__.to_s(16)} #{thread.status || 'dead'}]  #{lock_state}\n"

変更後:

msg = +"#{owner.class} #{info[:index]} [0x#{owner.__id__.to_s(16)} #{owner_status(owner)}]  #{lock_state}\n"

テストとしてShareLockFiberTestが追加されました。isolation_level:fiberに設定したうえで、start_exclusive(no_wait: true)と手動のFiber.resumeを組み合わせることで、Fiberスケジューラなしに自己完結したかたちで所有権セマンティクスを検証しています。同一スレッド上の2つのFiberが独立した所有者として認識されること、および既存の:threadアイソレーションでは複数のFiberが単一オーナーに集約されることの両方を確認しています。

設計判断

既存のIsolatedExecutionState.contextを採用することで、フレームワーク全体での「現在の実行コンテキスト」定義との一貫性を確保しました。

PRの説明にあるように、CurrentAttributesなど他のフレームワーク機能が既にこのAPIを使用しているため、ShareLockも同じスコープを使うことは自然な選択です。:threadアイソレーション(デフォルト)ではIsolatedExecutionState.contextThread.currentと同じオブジェクトを返すため、既存の動作は変わりません。変更の影響はFiberアイソレーションを明示的に設定した場合のみ現れます。

変数名のthreadownerへの改名はリネームに留まらず、保持するオブジェクトの型がFiberである可能性を明示的に認めるという意味を持ちます。PRの説明でも「フィールドがFiberを保持している場合にスレッドと主張すべきではない」と述べられており、APIの正確さを重視した判断といえます。

まとめ

この修正は、ShareLockのオーナーシップ識別を1箇所変更することで、Fiberスケジューラ環境での深刻な競合状態を解消しています。IsolatedExecutionState.contextへの統一により、Railsフレームワーク全体で「実行コンテキスト」の概念が一元化され、今後の新たなアイソレーションレベルへの対応も容易になります。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
8863af77

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文(総論)→背景・技術詳細・設計判断(各論)→まとめ(結論)の3部構成が明確に適用されており、ガイドラインに完全に準拠しています。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きのシンタックスハイライトやPRへのリンク記法が正しく使用されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

内容はRailsの内部並行処理メカニズムに関するもので、専門知識を持つエンジニアという対象読者に完全に適合しています。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションが総論→各論の構成になっており、各段落はトピックセンテンスで始まるなど、パラグラフ・ライティングの原則が守られています。非常に読みやすい構成です。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事内で引用されているコードブロックは、提供されたDiff情報と正確に一致しています。変更前後のコードが適切に示されています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`ShareLock`, `IsolatedExecutionState`, `Fiberアイソレーション`などの技術用語が、PRの文脈に沿って正確に使用されています。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

Fiberアイソレーション下で発生する競合状態の原因と、その解決策に関する技術的な説明は、PRの内容と完全に一致しており、論理的かつ正確です。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事内のすべての主張(問題の背景、技術的変更、設計判断)は、PRのDescriptionやDiff情報によって裏付けられており、ハルシネーションは検出されませんでした。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号(#57423)、クラス名、メソッド名などの固有名詞はすべて正確です。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事のタイトルは、PRのタイトル「Fix ShareLock ownership under :fiber isolation」の内容を、より具体的かつ分かりやすく要約しており、主題と完全に一致しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

PRで言及されていない外部知識(バージョンのサポート状況など)は含まれておらず、すべての情報が提供された資料に基づいています。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

「既に使われている」などの時間表現は、PR内の "already use" といった表現と一致しており、正確です。