Fix ConcurrentMapNative snapshot views to avoid CME during iteration#5504
Fix ConcurrentMapNative snapshot views to avoid CME during iteration#5504dapzthelegend wants to merge 3 commits intoktorio:mainfrom
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe posix Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@ktor-utils/posix/src/io/ktor/util/collections/ConcurrentMapNative.kt`:
- Around line 45-54: The Posix implementation in ConcurrentMapNative.kt
currently returns snapshot collections for entries/keys/values (using
LinkedHashSet/ArrayList) which diverges from JVM/Web live-view semantics; change
entries, keys and values to return synchronized live views that proxy mutations
to the underlying delegate map instead of snapshots: implement small wrapper
classes (e.g., an AbstractMutableSet for entries that delegates
contains/add/remove/iterator/size operations to delegate inside
synchronized(lock), similarly for keys and a MutableCollection for values) and
reuse DetachedMutableEntry only for iterator elements if needed so mutation
methods (remove/add/clear) affect delegate; keep synchronization via the
existing lock and ensure iterator.remove and entry.setValue update the
underlying delegate.
- Around line 88-102: DetachedMutableEntry currently only holds key/value and
doesn't override equals/hashCode, causing entry-set containers (e.g., the
LinkedHashSet returned by entries) to use reference equality; implement
value-based equality by overriding equals(other: Any?) and hashCode() on
DetachedMutableEntry to compare key and value (consistent with
MutableMap.MutableEntry contract) and update setValue to not change equality
semantics, then add tests asserting entries.contains and entries.remove work for
distinct entry instances with equal key/value pairs (verifying entry equality
and hash behavior).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: cdb14083-bf9d-44b5-95af-3bae8446bb7a
📒 Files selected for processing (2)
ktor-utils/posix/src/io/ktor/util/collections/ConcurrentMapNative.ktktor-utils/posix/test/io/ktor/util/collections/ConcurrentMapNativeTest.kt
Co-Authored-By: Paperclip <noreply@paperclip.ing>
|
Follow-up update pushed for the CodeRabbit review.
Validation:
I also replied in-thread on the snapshot-view comment with rationale for keeping Native snapshot semantics to avoid reintroducing the #5480 CME path. |
|
Follow-up update pushed to close the remaining snapshot-semantics thread.
Validation:
|
Summary
Fixes #5480 by returning detached snapshot collections from
ConcurrentMapNativeview properties.entriesnow returns a copied set of detached mutable entrieskeysnow returns a copied setvaluesnow returns a copied listThis prevents iterating over map views from throwing
ConcurrentModificationExceptionwhen the backing map is mutated concurrently or during teardown flows.Tests
Added
ConcurrentMapNativeTestunderktor-utils/posix/test:entries returns snapshotkeys returns snapshotvalues returns snapshotVerification
./gradlew :ktor-utils:formatKotlin./gradlew :ktor-utils:lintKotlin./gradlew :ktor-utils:assemble./gradlew :ktor-utils:jvmTest :ktor-utils:macosArm64Test(macosArm64Testis build-gated and skipped by task config)./gradlew :ktor-utils:linkDebugTestMacosX64./ktor-utils/build/bin/macosX64/debugTest/test.kexe./ktor-utils/build/bin/macosX64/debugTest/test.kexe '--ktest_filter=io.ktor.util.collections.ConcurrentMapNativeTest.*'