Root cause
ConcurrentMapNative.entries returns the raw LinkedHashMap delegate's entries under a lock, but iteration happens outside the lock. When an entry is modified/removed during iteration (e.g., CIOEngine.close() iterating endpoints while endpoint.close() triggers onDone callback that removes entries), a ConcurrentModificationException is thrown.
File: ktor-utils/posix/src/io/ktor/util/collections/ConcurrentMapNative.kt
actual override val entries: MutableSet<MutableMap.MutableEntry<Key, Value>>
get() = synchronized(lock) { delegate.entries } // returns raw view, not a copy
The same issue exists for keys and values properties.
Observed in CI
io.ktor.client.tests.ContentTest.testEmptyContent[mingwX64] — ConcurrentModificationException at HashMap.EntriesItr#checkForComodification → CIOEngine#close
- Intermittent across macOS/Windows native targets
Suggested fix
Return a snapshot copy instead of the raw delegate view:
actual override val entries: MutableSet<MutableMap.MutableEntry<Key, Value>>
get() = synchronized(lock) { LinkedHashSet(delegate.entries) }
Or better: make CIOEngine.close() collect endpoint values before iterating.
Context
Discovered while investigating CI failures on PR #5379 (CaseInsensitiveMap). The failures are unrelated to that PR's changes.
Root cause
ConcurrentMapNative.entriesreturns the rawLinkedHashMapdelegate's entries under a lock, but iteration happens outside the lock. When an entry is modified/removed during iteration (e.g.,CIOEngine.close()iterating endpoints whileendpoint.close()triggersonDonecallback that removes entries), aConcurrentModificationExceptionis thrown.File:
ktor-utils/posix/src/io/ktor/util/collections/ConcurrentMapNative.ktThe same issue exists for
keysandvaluesproperties.Observed in CI
io.ktor.client.tests.ContentTest.testEmptyContent[mingwX64]—ConcurrentModificationExceptionatHashMap.EntriesItr#checkForComodification→CIOEngine#closeSuggested fix
Return a snapshot copy instead of the raw delegate view:
Or better: make
CIOEngine.close()collect endpoint values before iterating.Context
Discovered while investigating CI failures on PR #5379 (CaseInsensitiveMap). The failures are unrelated to that PR's changes.