Skip to content

Conversation

@orien
Copy link
Member

@orien orien commented Dec 28, 2025

Context

The locking mechanism used a class variable (@@locks) indexed by Thread.current.object_id to track account locks. This implementation had three critical defects:

  1. Object ID reuse vulnerability: Ruby can reuse object IDs after garbage collection, allowing new threads to inadvertently access stale locks from terminated threads
  2. Race conditions: The shared class variable lacked thread synchronisation, creating potential data races
  3. Memory leaks: Lock entries from dead threads were never cleaned up, causing unbounded memory growth in long-running applications

Changes

  • Removed the @@locks class variable
  • Replaced object ID-based indexing with Ruby's built-in thread-local storage (Thread.current[:double_entry_locks])
  • Updated locks, locks=, and remove_locks methods to use thread-local variables

Consequences

This fix ensures proper thread isolation without API changes. Thread-local variables are automatically cleaned up when threads terminate, eliminating memory leaks. The implementation is now both safer and more idiomatic Ruby.

The previous implementation stored locks in a class variable indexed
by Thread.current.object_id, which had three critical defects:

1. Object ID reuse: Ruby can reuse object IDs after garbage collection,
   allowing new threads to inadvertently access stale locks from dead
   threads
2. Race conditions: The shared @@locks class variable was not
   thread-safe, creating potential race conditions
3. Memory leaks: Dead thread entries were not automatically cleaned up

This fix replaces the class variable with Ruby's built-in thread-local
storage (Thread.current[:double_entry_locks]), which:
- Ties data directly to the thread object, not its object ID
- Provides isolated storage per thread
- Automatically cleans up when threads terminate
Copy link

@petervandoros petervandoros left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! 👍

@orien orien merged commit 6409da4 into main Jan 5, 2026
106 of 108 checks passed
@orien orien deleted the locking branch January 5, 2026 00:08
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.

3 participants