ktorio / ktor

Framework for quickly creating connected applications in Kotlin with minimal effort
https://ktor.io
Apache License 2.0
12.86k stars 1.04k forks source link

Fix ConcurrentModificationException in SelectorHelper #4281

Closed Thomas-Vos closed 3 weeks ago

Thomas-Vos commented 3 weeks ago

Subsystem ktor-network

Motivation Received the following crash report on iOS:

          Non-fatal Exception: ConcurrentModificationException
0  RemoteGamepad                  0x141330 kfun:kotlin.collections.HashMap.Itr#checkForComodification(){} + 593 (HashMap.kt:593)
1  RemoteGamepad                  0x141398 kfun:kotlin.collections.HashMap.KeysItr#next(){}1:0 + 600 (HashMap.kt:600)
2  RemoteGamepad                  0xdbb904 kfun:kotlin.collections.Iterator#next(){}1:0-trampoline + 18 (Iterator.kt:18)
3  RemoteGamepad                  0xaef308 kfun:io.ktor.network.selector.SelectorHelper.selectionLoop#internal + 1863 (_Collections.kt:1863)
4  RemoteGamepad                  0xaf0b1c kfun:io.ktor.network.selector.SelectorHelper.$start$lambda$0$FUNCTION_REFERENCE$0.invoke#internal + 53 (SelectUtilsNix.kt:53)
5  RemoteGamepad                  0xdbab3c kfun:kotlin.Function2#invoke(1:0;1:1){}1:2-trampoline + 1 ([K][Suspend]Functions:1)
6  RemoteGamepad                  0x10cafc kfun:kotlin.coroutines.intrinsics.object-3.invokeSuspend#internal + 72 (IntrinsicsNative.kt:72)
7  RemoteGamepad                  0x10b2ac kfun:kotlin.coroutines.native.internal.BaseContinuationImpl#resumeWith(kotlin.Result<kotlin.Any?>){} + 50 (ContinuationImpl.kt:50)
8  RemoteGamepad                  0x2064c0 kfun:kotlinx.coroutines.DispatchedTask#run(){} + 1 (Result.kt:1)
9  RemoteGamepad                  0x219ec8 kfun:kotlinx.coroutines.MultiWorkerDispatcher.$workerRunLoop$lambda$2COROUTINE$0.invokeSuspend#internal + 106 (MultithreadedDispatchers.kt:106)
10 RemoteGamepad                  0x21a68c kfun:kotlinx.coroutines.MultiWorkerDispatcher.$workerRunLoop$lambda$2$FUNCTION_REFERENCE$3.invoke#internal + 98 (MultithreadedDispatchers.kt:98)
11 RemoteGamepad                  0xdbab3c kfun:kotlin.Function2#invoke(1:0;1:1){}1:2-trampoline + 1 ([K][Suspend]Functions:1)
12 RemoteGamepad                  0x10cafc kfun:kotlin.coroutines.intrinsics.object-3.invokeSuspend#internal + 72 (IntrinsicsNative.kt:72)
13 RemoteGamepad                  0x10b2ac kfun:kotlin.coroutines.native.internal.BaseContinuationImpl#resumeWith(kotlin.Result<kotlin.Any?>){} + 50 (ContinuationImpl.kt:50)
14 RemoteGamepad                  0x2064c0 kfun:kotlinx.coroutines.DispatchedTask#run(){} + 1 (Result.kt:1)
15 RemoteGamepad                  0x1cd2ec kfun:kotlinx.coroutines.EventLoopImplBase#processNextEvent(){}kotlin.Long + 15 (ObjectiveCUtils.kt:15)
16 RemoteGamepad                  0x215078 kfun:kotlinx.coroutines#runBlocking(kotlin.coroutines.CoroutineContext;kotlin.coroutines.SuspendFunction1<kotlinx.coroutines.CoroutineScope,0:0>){0§<kotlin.Any?>}0:0 + 49 (EventLoop.common.kt:49)
17 RemoteGamepad                  0x21a844 kfun:kotlinx.coroutines.MultiWorkerDispatcher.$<init>$lambda$1$lambda$0$FUNCTION_REFERENCE$5.$<bridge-DNN>invoke(){}#internal + 72 (Builders.kt:72)
18 RemoteGamepad                  0xdb90c0 kfun:kotlin.Function0#invoke(){}1:0-trampoline + 1 ([K][Suspend]Functions:1)
19 RemoteGamepad                  0x131ace0 Worker::processQueueElement(bool)
20 RemoteGamepad                  0x131a7cc (anonymous namespace)::workerRoutine(void*)
21 libsystem_pthread.dylib        0x30ec _pthread_start
22 libsystem_pthread.dylib        0x172c thread_start

Solution Fixed the issue which was unfortunately not caught in the tests. The existing test testDescriptorErrorDoesNotFailOtherSockets verifies the behaviour is still correct.