Problem with the new version of kotlinx-coroutines-play-services into my code

5.3k Views Asked by At

I already added coroutine play services into my code, everything was working find, but after updating coroutines to the version 1.3.2, my application crash and give me the error bellow, but into the stack trace it is not possible to see the origin of the error in my code, I tried to use the breack points and then I notice that de error occurred into the cancelation of the flowawaitClose {cancel()} . The stack trace is:

    2021-08-04 09:40:30.976 11200-11200/com.kola.kolaapplication.dev E/AndroidRuntime: FATAL EXCEPTION: main
    java.lang.IllegalStateException: 'awaitClose { yourCallbackOrListener.cancel() }' should be used in the end of callbackFlow block.
    Otherwise, a callback/listener may leak in case of external cancellation.
    Process: com.kola.kolaapplication.dev, PID: 11200
    See callbackFlow API documentation for the details.
2021-08-04 09:40:30.976 11200-11200/com.kola.kolaapplication.dev E/AndroidRuntime: FATAL EXCEPTION: main
    java.lang.IllegalStateException: 'awaitClose { yourCallbackOrListener.cancel() }' should be used in the end of callbackFlow block.
        at kotlinx.coroutines.flow.CallbackFlowBuilder.collectTo(Builders.kt:362)
    Process: com.kola.kolaapplication.dev, PID: 11200
    Otherwise, a callback/listener may leak in case of external cancellation.
        at kotlinx.coroutines.flow.CallbackFlowBuilder$collectTo$1.invokeSuspend(Unknown Source:15)
    See callbackFlow API documentation for the details.
    java.lang.IllegalStateException: 'awaitClose { yourCallbackOrListener.cancel() }' should be used in the end of callbackFlow block.
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.flow.CallbackFlowBuilder.collectTo(Builders.kt:362)
    Otherwise, a callback/listener may leak in case of external cancellation.
        at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:234)
    See callbackFlow API documentation for the details.
        at kotlinx.coroutines.flow.CallbackFlowBuilder$collectTo$1.invokeSuspend(Unknown Source:15)
        at kotlinx.coroutines.DispatchedTaskKt.resumeUnconfined(DispatchedTask.kt:190)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.flow.CallbackFlowBuilder.collectTo(Builders.kt:362)
        at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:161)
        at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:234)
        at kotlinx.coroutines.flow.CallbackFlowBuilder$collectTo$1.invokeSuspend(Unknown Source:15)
        at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:398)
        at kotlinx.coroutines.DispatchedTaskKt.resumeUnconfined(DispatchedTask.kt:190)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.CancellableContinuationImpl.cancel(CancellableContinuationImpl.kt:184)
        at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:161)
        at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:234)
        at kotlinx.coroutines.CancellableContinuationImpl.parentCancelled$kotlinx_coroutines_core(CancellableContinuationImpl.kt:191)
        at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:398)
        at kotlinx.coroutines.DispatchedTaskKt.resumeUnconfined(DispatchedTask.kt:190)
        at kotlinx.coroutines.ChildContinuation.invoke(JobSupport.kt:1474)
        at kotlinx.coroutines.CancellableContinuationImpl.cancel(CancellableContinuationImpl.kt:184)
        at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:161)
        at kotlinx.coroutines.JobSupport.notifyCancelling(JobSupport.kt:1499)
        at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:398)
        at kotlinx.coroutines.CancellableContinuationImpl.parentCancelled$kotlinx_coroutines_core(CancellableContinuationImpl.kt:191)
        at kotlinx.coroutines.JobSupport.tryMakeCancelling(JobSupport.kt:795)
        at kotlinx.coroutines.ChildContinuation.invoke(JobSupport.kt:1474)
        at kotlinx.coroutines.CancellableContinuationImpl.cancel(CancellableContinuationImpl.kt:184)
        at kotlinx.coroutines.JobSupport.makeCancelling(JobSupport.kt:755)
        at kotlinx.coroutines.JobSupport.notifyCancelling(JobSupport.kt:1499)
        at kotlinx.coroutines.JobSupport.cancelImpl$kotlinx_coroutines_core(JobSupport.kt:671)
        at kotlinx.coroutines.CancellableContinuationImpl.parentCancelled$kotlinx_coroutines_core(CancellableContinuationImpl.kt:191)
        at kotlinx.coroutines.JobSupport.tryMakeCancelling(JobSupport.kt:795)
        at kotlinx.coroutines.JobSupport.parentCancelled(JobSupport.kt:637)
        at kotlinx.coroutines.ChildContinuation.invoke(JobSupport.kt:1474)
        at kotlinx.coroutines.JobSupport.makeCancelling(JobSupport.kt:755)
        at kotlinx.coroutines.ChildHandleNode.invoke(JobSupport.kt:1465)
        at kotlinx.coroutines.JobSupport.notifyCancelling(JobSupport.kt:1499)
        at kotlinx.coroutines.JobSupport.cancelImpl$kotlinx_coroutines_core(JobSupport.kt:671)
        at kotlinx.coroutines.JobSupport.notifyCancelling(JobSupport.kt:1499)
        at kotlinx.coroutines.JobSupport.tryMakeCancelling(JobSupport.kt:795)
        at kotlinx.coroutines.JobSupport.parentCancelled(JobSupport.kt:637)
        at kotlinx.coroutines.JobSupport.tryMakeCancelling(JobSupport.kt:795)
        at kotlinx.coroutines.JobSupport.makeCancelling(JobSupport.kt:755)
        at kotlinx.coroutines.ChildHandleNode.invoke(JobSupport.kt:1465)
        at kotlinx.coroutines.JobSupport.makeCancelling(JobSupport.kt:755)
        at kotlinx.coroutines.JobSupport.cancelImpl$kotlinx_coroutines_core(JobSupport.kt:671)
        at kotlinx.coroutines.JobSupport.notifyCancelling(JobSupport.kt:1499)
        at kotlinx.coroutines.JobSupport.cancelImpl$kotlinx_coroutines_core(JobSupport.kt:671)
        at kotlinx.coroutines.JobSupport.parentCancelled(JobSupport.kt:637)
        at kotlinx.coroutines.JobSupport.tryMakeCancelling(JobSupport.kt:795)
        at kotlinx.coroutines.JobSupport.parentCancelled(JobSupport.kt:637)
        at kotlinx.coroutines.ChildHandleNode.invoke(JobSupport.kt:1465)
        at kotlinx.coroutines.JobSupport.makeCancelling(JobSupport.kt:755)
        at kotlinx.coroutines.ChildHandleNode.invoke(JobSupport.kt:1465)
        at kotlinx.coroutines.JobSupport.notifyCancelling(JobSupport.kt:1499)
        at kotlinx.coroutines.JobSupport.cancelImpl$kotlinx_coroutines_core(JobSupport.kt:671)
        at kotlinx.coroutines.JobSupport.notifyCancelling(JobSupport.kt:1499)
        at kotlinx.coroutines.JobSupport.tryMakeCancelling(JobSupport.kt:795)
        at kotlinx.coroutines.JobSupport.parentCancelled(JobSupport.kt:637)
        at kotlinx.coroutines.JobSupport.tryMakeCancelling(JobSupport.kt:795)
        at kotlinx.coroutines.JobSupport.makeCancelling(JobSupport.kt:755)
        at kotlinx.coroutines.ChildHandleNode.invoke(JobSupport.kt:1465)
        at kotlinx.coroutines.JobSupport.makeCancelling(JobSupport.kt:755)
        at kotlinx.coroutines.JobSupport.cancelImpl$kotlinx_coroutines_core(JobSupport.kt:671)
        at kotlinx.coroutines.JobSupport.notifyCancelling(JobSupport.kt:1499)
        at kotlinx.coroutines.JobSupport.cancelImpl$kotlinx_coroutines_core(JobSupport.kt:671)
        at kotlinx.coroutines.JobSupport.parentCancelled(JobSupport.kt:637)
        at kotlinx.coroutines.JobSupport.tryMakeCancelling(JobSupport.kt:795)
        at kotlinx.coroutines.JobSupport.makeCancelling(JobSupport.kt:755)
        at kotlinx.coroutines.JobSupport.cancelImpl$kotlinx_coroutines_core(JobSupport.kt:671)
        at kotlinx.coroutines.JobSupport.parentCancelled(JobSupport.kt:637)
        at kotlinx.coroutines.ChildHandleNode.invoke(JobSupport.kt:1465)
        at kotlinx.coroutines.JobSupport.notifyCancelling(JobSupport.kt:1499)
        at kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath(JobSupport.kt:900)
        at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:863)
        at kotlinx.coroutines.JobSupport.cancelMakeCompleting(JobSupport.kt:696)
        at kotlinx.coroutines.JobSupport.cancelImpl$kotlinx_coroutines_core(JobSupport.kt:667)
        at kotlinx.coroutines.JobSupport.cancelInternal(JobSupport.kt:632)
        at kotlinx.coroutines.JobSupport.cancel(JobSupport.kt:617)
        at kotlinx.coroutines.JobKt__JobKt.cancel(Job.kt:561)
        at kotlinx.coroutines.JobKt.cancel(Unknown Source:1)
        at kotlinx.coroutines.JobKt__JobKt.cancel$default(Job.kt:560)
        at kotlinx.coroutines.JobKt.cancel$default(Unknown Source:1)
        at androidx.lifecycle.CloseableCoroutineScope.close(ViewModel.kt:51)
        at androidx.lifecycle.ViewModel.closeWithRuntimeException(ViewModel.java:188)
        at androidx.lifecycle.ViewModel.clear(ViewModel.java:134)
        at androidx.lifecycle.ViewModelStore.clear(ViewModelStore.java:62)
        at androidx.fragment.app.FragmentManagerViewModel.clearNonConfigState(FragmentManagerViewModel.java:199)
        at androidx.fragment.app.FragmentStateManager.destroy(FragmentStateManager.java:772)
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:350)
        at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:112)
        at kotlinx.coroutines.ChildHandleNode.invoke(JobSupport.kt:1465)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1647)
        at kotlinx.coroutines.JobSupport.notifyCancelling(JobSupport.kt:1499)
2021-08-04 09:40:30.980 11200-11200/com.kola.kolaapplication.dev E/AndroidRuntime:     at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3126)
        at kotlinx.coroutines.JobSupport.parentCancelled(JobSupport.kt:637)
        at kotlinx.coroutines.JobSupport.tryMakeCancelling(JobSupport.kt:795)
        at androidx.fragment.app.FragmentManager.dispatchDestroy(FragmentManager.java:3105)
        at kotlinx.coroutines.ChildHandleNode.invoke(JobSupport.kt:1465)
        at androidx.fragment.app.Fragment.performDestroy(Fragment.java:3214)
        at kotlinx.coroutines.JobSupport.makeCancelling(JobSupport.kt:755)
        at androidx.fragment.app.FragmentStateManager.destroy(FragmentStateManager.java:774)
        at kotlinx.coroutines.JobSupport.notifyCancelling(JobSupport.kt:1499)
        at kotlinx.coroutines.JobSupport.cancelImpl$kotlinx_coroutines_core(JobSupport.kt:671)
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:350)
        at kotlinx.coroutines.JobSupport.parentCancelled(JobSupport.kt:637)
        at kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath(JobSupport.kt:900)
        at androidx.fragment.app.SpecialEffectsController$FragmentStateManagerOperation.complete(SpecialEffectsController.java:742)
        at androidx.fragment.app.SpecialEffectsController$Operation.cancel(SpecialEffectsController.java:594)
        at kotlinx.coroutines.ChildHandleNode.invoke(JobSupport.kt:1465)
        at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:863)
        at androidx.fragment.app.SpecialEffectsController.forceCompleteAllOperations(SpecialEffectsController.java:329)
        at kotlinx.coroutines.JobSupport.notifyCancelling(JobSupport.kt:1499)
        at kotlinx.coroutines.JobSupport.cancelMakeCompleting(JobSupport.kt:696)
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3130)
        at androidx.fragment.app.FragmentManager.dispatchDestroy(FragmentManager.java:3105)
        at kotlinx.coroutines.JobSupport.cancelImpl$kotlinx_coroutines_core(JobSupport.kt:667)
        at kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath(JobSupport.kt:900)
        at androidx.fragment.app.FragmentController.dispatchDestroy(FragmentController.java:334)
        at androidx.fragment.app.FragmentActivity.onDestroy(FragmentActivity.java:330)
        at kotlinx.coroutines.JobSupport.cancelInternal(JobSupport.kt:632)
        at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:863)
        at androidx.appcompat.app.AppCompatActivity.onDestroy(AppCompatActivity.java:242)
        at android.app.Activity.performDestroy(Activity.java:8865)
        at kotlinx.coroutines.JobSupport.cancel(JobSupport.kt:617)
        at kotlinx.coroutines.JobSupport.cancelMakeCompleting(JobSupport.kt:696)
        at android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1316)
        at kotlinx.coroutines.JobKt__JobKt.cancel(Job.kt:561)
        at kotlinx.coroutines.JobSupport.cancelImpl$kotlinx_coroutines_core(JobSupport.kt:667)
        at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:4539)
        at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:4572)
        at kotlinx.coroutines.JobKt.cancel(Unknown Source:1)
        at kotlinx.coroutines.JobSupport.cancelInternal(JobSupport.kt:632)
        at android.app.servertransaction.DestroyActivityItem.execute(DestroyActivityItem.java:39)
        at kotlinx.coroutines.JobSupport.cancel(JobSupport.kt:617)
        at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:145)
        at kotlinx.coroutines.JobKt__JobKt.cancel$default(Job.kt:560)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1830)
        at kotlinx.coroutines.JobKt.cancel$default(Unknown Source:1)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at kotlinx.coroutines.JobKt__JobKt.cancel(Job.kt:561)
        at androidx.lifecycle.CloseableCoroutineScope.close(ViewModel.kt:51)
        at android.os.Looper.loop(Looper.java:193)
        at kotlinx.coroutines.JobKt.cancel(Unknown Source:1)
        at android.app.ActivityThread.main(ActivityThread.java:6914)
        at androidx.lifecycle.ViewModel.closeWithRuntimeException(ViewModel.java:188)
        at java.lang.reflect.Method.invoke(Native Method)
        at kotlinx.coroutines.JobKt__JobKt.cancel$default(Job.kt:560)
        at androidx.lifecycle.ViewModel.clear(ViewModel.java:134)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:588)
        at kotlinx.coroutines.JobKt.cancel$default(Unknown Source:1)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
        at androidx.lifecycle.ViewModelStore.clear(ViewModelStore.java:62)
        at androidx.lifecycle.CloseableCoroutineScope.close(ViewModel.kt:51)
        at androidx.fragment.app.FragmentManagerViewModel.clearNonConfigState(FragmentManagerViewModel.java:199)

**Coroutine into my gradle file:**
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.3.2'

My code:

val curentUserDocRef: DocumentReference
    get() = firestoreInstance.document(
        commonFireStoreRefKeyWord.USERS_COLLECTION_REF.plus(
            "/${FireStoreAuthUtil.getUserUID()}"
        )
    )

 fun saveUserToFireStore(newUser: KUser): Flow<FirebaseResponseType<KUser>> = callbackFlow{

    curentUserDocRef.get().addOnSuccessListener { documentSnapshot ->
        //Get the user into firebase firestore
        if (!documentSnapshot.exists()) {
           //If the user does not exist, we save it
            curentUserDocRef.set(newUser)
                .addOnSuccessListener {
                    
                try {
                        
                 this.trySend(FirebaseResponseType.FirebaseSuccessResponse(newUser)).isSuccess
                } catch (ex: Exception) {
                   ex.printStackTrace()
                   Log(ex.message)
                   cancel()
                }
        } else {
            // If the user already save, we don't save it anymore
            val userData = documentSnapshot.toObject(KUser::class.java)
            try {
                this.trySend(FirebaseResponseType.FirebaseSuccessResponse(userData)).isSuccess
            } catch (ex: Exception) {
                ex.printStackTrace()
                cLog(ex.message)
                cancel()
            }
        }
    }.addOnFailureListener {
        it.printStackTrace()
        cLog(it.message)
        try {
            this.trySend(FirebaseResponseType.FirebaseErrorResponse(it)).isSuccess
        } catch (ex: Exception) {
            ex.printStackTrace()
            cLog(ex.message)
            printLogD(TAG, ex.message ?: "")
        }
        cancel()
    }

    try {
        awaitClose {
            cancel()  // **I think the error occured here**
        }
    } catch (ex: Exception) {
        ex.printStackTrace()
        cLog(ex.message)
        printLogD(TAG, ex.message ?: "")
    }

}

Into the preview version of coroutine play service, I was using offer() intead of trySend(), But into coroutine coroutines-play-services:1.3.2, the offer() method is deprecated, they ask to use trySend().

What should be done to resolve this problem Please, I have been looking for the solution for a week already

1

There are 1 best solutions below

5
On BEST ANSWER

I had the same problem when I change offer by trySend in my callbackFlow.

I notice that when I close the scope instead of the channel my application crashes.

So to solve my problem, I used awaitClose { channel.close() } instead of awaitClose { cancel() }.