Skip to content

Conversation

@merouaneamqor
Copy link

@merouaneamqor merouaneamqor commented Sep 18, 2025

This PR addresses a rare thread safety issue in IdentityCache's recursive association hydration, where concurrent access to the same record's dehydrated instance variables could cause a NameError when trying to remove an already-deleted ivar.
Problem
As described in issue #568, multiple threads calling fetch_relation (or similar cached accessors) on the same record can trigger a race condition:

  • Race condition scenario:

    • Thread A and Thread B both call read() on the same record.
    • Both check record.instance_variable_defined?(dehydrated_variable_name) → returns true.
    • Both proceed to hydrate and attempt to remove the ivar.
    • Thread A removes it first; Thread B gets NameError when trying to remove the already-gone ivar.

    This error manifests as:
    NameError: instance variable @dehydrated_relation not defined

Solution

Introduce a mutex to synchronize hydration, ensuring only one thread can hydrate a dehydrated association at a time. This prevents the race without over-serializing unrelated operations.

  • Added Mutex in Association#initialize for per-association locking.
  • Wrapped hydration logic in hydrate_safely with Mutex#synchronize.
  • Added defensive checks to avoid NameError even in edge cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant