davidepianca98/KMQTT

Error in recv: 9 on disconnect()

KirkBushman opened this issue ยท 12 comments

Ciao @davidepianca98 ๐Ÿ‘‹ ,

While testing a feature using KMM I noticed I get the following error:

--- Error: socket.IOException: Error in recv: 9
    at 0   Sdk                              0x121e217af        kfun:socket.tcp.Socket#read(){}kotlin.UByteArray? + 943 
    at 1   Sdk                              0x121e28baf        kfun:ClientSocket#read(){}kotlin.UByteArray? + 511 
    at 2   Sdk                              0x121f33a37        kfun:socket.SocketInterface#read(){}kotlin.UByteArray?-trampoline + 207 
    at 3   Sdk                              0x121e238bb        kfun:MQTTClient.check#internal + 235 
    at 4   Sdk                              0x121e2c1a7        kfun:kmp.backend.calls.MyMqttClientImpl.$subscribe$lambda$2$FUNCTION_REFERENCE$2.invoke#internal + 939 
    at 5   Sdk                              0x121f034b7        kfun:kotlin.Function2#invoke(1:0;1:1){}1:2-trampoline + 207 
    at 6   Sdk                              0x121a8b417        kfun:kotlin.coroutines.intrinsics.object-3.invokeSuspend#internal + 451 
    at 7   Sdk                              0x121a8a33b        kfun:kotlin.coroutines.native.internal.BaseContinuationImpl#resumeWith(kotlin.Result<kotlin.Any?>){} + 171 
    at 8   Sdk                              0x121b6710b        kfun:kotlinx.coroutines.DispatchedTask#run(){} + 471 
    at 9   Sdk                              0x121b789d7        kfun:kotlinx.coroutines.DarwinGlobalQueueDispatcher.$dispatch$lambda$0$FUNCTION_REFERENCE$0.$<bridge-UNN>invoke(){}#internal + 83 
    at 10  Sdk                              0x121f01443        kfun:kotlin.Function0#invoke(){}1:0-trampoline + 207 
    at 11  Sdk                              0x1221d3797        ___6f72672e6a6574627261696e732e6b6f746c696e783a6b6f746c696e782d636f726f7574696e65732d636f72652f6f70742f6275696c644167656e742f776f726b2f343465633665383530643563363366302f6b6f746c696e782d636f726f7574696e65732d636f72652f6e617469766544617277696e2f7372632f44697370617463686572732e6b74_knbridge2_block_invoke + 231 
    at 12  libdispatch.dylib                   0x110c1453b        _dispatch_call_block_and_release + 31 
    at 13  libdispatch.dylib                   0x110c15fef        _dispatch_client_callout + 19 
    at 14  libdispatch.dylib                   0x110c18b27        _dispatch_queue_override_invoke + 1051 
    at 15  libdispatch.dylib                   0x110c2a467        _dispatch_root_queue_drain + 407 
    at 16  libdispatch.dylib                   0x110c2ae63        _dispatch_worker_thread2 + 195 
    at 17  libsystem_pthread.dylib             0x1f733cdbb        _pthread_wqthread + 227 
    at 18  libsystem_pthread.dylib             0x1f733cb97        start_wqthread + 7 
 

It happens only when this line is present:

client.disconnect(ReasonCode.SUCCESS)

Also it only happens on iOS :/ It doesn't happen on Android.

Do you have any idea about how to fix this? Are we doing anything wrong? Can it be tied to the prebuilt .klibs we're bundling in the project for iOS to work?

Thanks in advance for your work

Hello, error 9 bad file descriptor, basically the socket has been closed. Are you still using the client after calling disconnect?

No I'm setting the client to null and cancelling the coroutines job right after that.

Can you please send a code snippet so that I can try to reproduce it?

@davidepianca98 Sure, I have an interface wrapping the client that has 2 methods: subscribe() / unsubscribe()

internal interface MyMqttClient {
    suspend fun subscribe(onReceive: (String) -> Unit)
    suspend fun unsubscribe()
}

here below is the rough implementation:

internal class MyMqttClientImpl {

    private var job: Job? = null
    private var client: MQTTClient? = null

    override suspend fun subscribe(onReceive: (String) -> Unit) {
        client = createMqttClient(onReceive)
        client?.let { client ->
            
            job = scope.launch {
                 try {
                     client.subscribe(listOf(Subscription("my_topic", SubscriptionOptions(Qos.EXACTLY_ONCE))))
                     client.run()
                 } catch (ex: Exception) {
                     // handle exception
                 }
           }
           job!!.start()
        }
    }
    override suspend fun unsubscribe() {
        client?.let { client ->
            client.unsubscribe(listOf("my_topic"))
            client.disconnect(ReasonCode.SUCCESS) // crashes here, doesn't crash without this line
        }

        job?.cancel()
        job = null

        client = null
    }

    private fun createMqttClient(onReceive: (String) -> Unit) {
        return MQTTClient(
            mqttVersion = MQTTVersion.MQTT5,
            address = "my_address",
            port = 1, // my port 
            clientId = "my_client_id",
            userName = "my_username",
            password = "my_password",
            tls = null,
        ) { publish ->
            // handle incoming events
        }
    }
}

After calling subscribe() and receiving some events, I just call unsubscribe() and get the crash.
Again, I wanna remind you that this above case works just fine on Android, but crashes on iOS

I was not able to reproduce the issue, but I think I have found what potentially can trigger the problem and should be fixed in commit 48cc990.
If you cannot wait for a new build to go out, you may try to either build yourself or do this modification to your code:

override suspend fun unsubscribe() {
      job?.cancel()
      job = null
      client?.let { client ->
          client.unsubscribe(listOf("my_topic"))
          client.disconnect(ReasonCode.SUCCESS) // crashes here, doesn't crash without this line
      }

      client = null
}

@davidepianca98 Thanks a lot ๐Ÿ˜ƒ we can wait for a build.

Also please let met know if it works without errors with the code change I sent in the last message

@davidepianca98 Once the release is out, I'll report back

@davidepianca98 We've tried the fix above and we still get the same issue :(
Do you have an ETA as to when you're going to publish a new release?

Thanks for letting me know, hopefully during the weekend

Please let me know if the new release is working for you

@davidepianca98 It seems it's working now on iOS :) thanks