Search code examples
codenameone

Need you lights on iOS threads


I am working on a POC app on datagram sockets, I'm on the iOS part. It's a straightforward one screen app with a couple of buttons. Anyway, my issue is with the EDT thread, the GC thread and one of my IO threads. My IO thread has a bound datagram socket waiting for messages (recvfrom). Sometimes, I see that the EDT is stuck and when I look at the iOS threads stacks, I see that:

1 - The EDT thread is sleeping waiting for a boolean to turn false

while(threadStateData->threadBlockedByGC) {
    usleep(1000);
}
#3  0x0000000100e6ed02 in java_lang_Thread_sleep___long at /dist/MyApplication-src/nativeMethods.m:1231
#4  0x0000000101194c44 in java_lang_System_gc__ at /dist/MyApplication-src/java_lang_System.m:257
#5  0x0000000100c431c1 in codenameOneGcMalloc at /dist/MyApplication-src/cn1_globals.m:791
#6  0x00000001011bac4a in __NEW_com_codename1_ui_Label_1 at /dist/MyApplication-src/com_codename1_ui_Label_1.m:31
#7  0x0000000101491019 in com_codename1_ui_Label___INIT_____java_lang_String_java_lang_String at /dist/MyApplication-src/com_codename1_ui_Label.m:1402
...

2 - The GC thread is also sleeping waiting for another boolean to turn true

while(t->threadActive) {
   usleep(500);
#3  0x0000000100c428d6 in codenameOneGCMark at /dist/MyApplication-src/cn1_globals.m:426
#4  0x0000000100e6e950 in java_lang_System_gcMarkSweep__ at /dist/MyApplication-src/nativeMethods.m:1078
#5  0x000000010119521d in java_lang_System_access$200__ at /dist/MyApplication-src/java_lang_System.m:331
...

A quick watch on t shows the threadId=8
t   ThreadLocalData *   0x600001616eb0  0x0000600001616eb0
threadId    JAVA_LONG   8

3 - My IO thread seems to be the one with id 8 (the address in memory is the same as well)

A quick watch on threadStateData shows the threadId=8
threadStateData ThreadLocalData *   0x600001616eb0  0x0000600001616eb0
threadId    JAVA_LONG   8

ssize_t result = recvfrom(socketDescriptor, buffer, sob, 0, (struct sockaddr *)&receiveSockaddr, &receiveSockaddrLen);

#1  0x0000000101100a00 in -[net_etc_net_impl_NativeDatagramSocketImpl receive:param1:param2:param3:] at /dist/MyApplication-src/net_et_net_impl_NativeDatagramSocketImpl.m:131
#2  0x0000000101615f6b in net_etc_net_impl_NativeDatagramSocketImplCodenameOne_receive___int_int_java_lang_String_int_R_int at /dist/MyApplication-src/native_net_et_net_impl_NativeDatagramSocketImplCodenameOne.m:51
#3  0x0000000100f7fc9e in net_etc_net_impl_NativeDatagramSocketStub_receive___int_int_java_lang_String_int_R_int at /dist/MyApplication-src/net_etc_net_impl_NativeDatagramSocketStub.m:87
#4  0x0000000100d59939 in virtual_net_etc_net_impl_NativeDatagramSocket_receive___int_int_java_lang_String_int_R_int at /dist/MyApplication-src/net_etc_net_impl_NativeDatagramSocket.m:91
#5  0x000000010156690f in net_etc_net_DatagramSocket_receive___byte_1ARRAY_int_R_int at /dist/MyApplication-src/net_etceterum_net_DatagramSocket.m:215

So my question is: what can I do to prevent this?

Thanks for your help.

Emmanuel


Solution

  • See this code in our socket implementation. I suggest adding yield/resume calls in your code to let the GC work. Just make sure you don't do any Java based allocations during that time.

    What happens is this:

    • The GC needs to run so it loops over all the active threads and tries to collect
    • Your thread started on the Java side so it's marked as a GC thread
    • It's marked as alive
    • The GC wants it to suspend allocations so it can GC it
    • The thread is unaware of this because it's in C code for a long time... Deadlock