Skip to content

Ensure subclass set prevents concurrent modification#8603

Merged
headius merged 3 commits intojruby:masterfrom
headius:another_subclass_fix
Feb 5, 2025
Merged

Ensure subclass set prevents concurrent modification#8603
headius merged 3 commits intojruby:masterfrom
headius:another_subclass_fix

Conversation

@headius
Copy link
Member

@headius headius commented Jan 30, 2025

The new SubclassesWeakMap properly included read/write locking for the put and forEach methods, but unfortunately the remove and isEmpty methods were not overridden with locking. This went unnoticed until after the 9.4.11.0 release, leading to #8602.

This patch makes two modifications to ensure proper locking:

  • Instead of working with the full Map interface, and possibly missing other method uses in the future, this narrows the subclasses map interface to a RubyClassSet with only unique methods that we use. This guarantees only these methods can be called, and we can ensure they are implemented properly.
  • Add the missing locking to the remove method, now named removeClass.

Fixes #8602.

The new SubclassesWeakMap properly included read/write locking for
the `put` and `forEach` methods, but unfortunately the `remove`
and `isEmpty` methods were not overridden with locking. This went
unnoticed until after the 9.4.11.0 release, leading to
jruby#8602.

This patch makes two modifications to ensure proper locking:

* Instead of working with the full Map interface, and possibly
  missing other method uses in the future, this narrows the
  subclasses map interface to a RubyClassSet with only unique
  methods that we use. This guarantees only these methods can be
  called, and we can ensure they are implemented properly.
* Add the missing locking to the `remove` method, now named
  `removeClass`.

A subsequent commit will include a test of high-concurrency reading
and writing to these maps which fails prior to this commit and
passes afterwards.

Fixes jruby#8602.
This should also test included hierarchy walking and manipulation,
which utilizes the same data structure.

See jruby#8602
@headius headius added this to the JRuby 9.4.12.0 milestone Jan 30, 2025
@headius
Copy link
Member Author

headius commented Feb 3, 2025

An additional change may be needed here due to several read operations mutating the collection to clean out stale entries. We may need to return to a fully locked implementation while using this implementation of WeakHashMap.

Because this is a weak set, it may mutate itself during read
operations to clean up dead references. A read lock is not
sufficient to guarantee the collection's integrity under these
circumstances, so I replace the read/write locking with a standard
ReentrantLock for all supported operations.
@headius headius merged commit 46e206c into jruby:master Feb 5, 2025
95 checks passed
@headius headius deleted the another_subclass_fix branch February 5, 2025 17:07
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.

ConcurrentModificationException in subclasses map

1 participant