Kotlinx.coroutines: Android app with coroutines 0.30.1-eap13 crashes in runtime

Created on 3 Oct 2018  Â·  22Comments  Â·  Source: Kotlin/kotlinx.coroutines

java.lang.IllegalStateException: Module with Main dispatcher is missing. Add dependency with required Main dispatcher, e.g. 'kotlinx-coroutines-android'
        at kotlinx.coroutines.Dispatchers.getMain(Dispatchers.kt:61)

kotlinx-coroutines-android is obviously added.
Version 0.30.0-eap13 works fine.

Most helpful comment

The same issue with 0.30.1 in release build only (i. e. when minifyEnabled true is specified)

Android Studio 3.1.2
Build #AI-173.4720617, built on April 14, 2018
JRE: 1.8.0_152-release-1024-b01 x86_64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Mac OS X 10.13.4

Didn't work:

-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}

Worked:

-keepnames class kotlinx.** { *; }

All 22 comments

Could you please provide a self-contained example? Or check why loadMainDispatcher loads nothing?

Could you please provide a self-contained example?

It is enough to start any coroutine in UI context. For example:
GlobalScope.launch(Dispatchers.Main) { ... }

Or check why loadMainDispatcher loads nothing?

ServiceLoader is unable to load MainDispatcherFactory.

It is enough to start any coroutine in UI context.

I did it in sample Android project and it works in both debug and release mode.

ServiceLoader is unable to load MainDispatcherFactory.

Again, works on my machine.

Please be cooperative. I'm willing to help you, but I can't do anything with reports like "it doesn't work"

It was my fault. I've excluded some Kotlin meta files from APK (specifically, Meta-inf/services/**). It was safe for previous coroutines version, but for 0.30.1 it became destructive.
Sorry that wasted your time.

If an app is obfustacted with default proguard settings, it crashes in runtime. Here is sample project to reproduce an issue: https://www.dropbox.com/s/eay696h9qmxjl5e/sample.zip?dl=1
UPD: I've created PR #662 but it will not work, because @Keep annotation is Android specific.
Is the only way to add proguard rules?

-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}

I had this bug when exported file apk when using proguard with the version 0.30.2.

Those proguard rules didn't work for me, so I used this:

-keepnames class kotlinx.** { *; }

Definitely not a great solution since it tells proguard to keep everything, but it works.

Same issue here with 0.30.2.

The same issue with 0.30.1 in release build only (i. e. when minifyEnabled true is specified)

Android Studio 3.1.2
Build #AI-173.4720617, built on April 14, 2018
JRE: 1.8.0_152-release-1024-b01 x86_64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Mac OS X 10.13.4

Didn't work:

-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}

Worked:

-keepnames class kotlinx.** { *; }

Thank you @trashkalmar for the reproducer.
Jettifier seems to have an issue with ServiceLoader and name mangling.

I have (ugly as hell) fix which first tries to lookup main dispatcher in service loader and then invokes Class.forName("...") for android factory. It will be fixed in 1.0.0-RC

This happens to me even without jetfier. Just proguard on its enough.

It would be great if kotlinx.coroutines library could include proguard rules as part of distribution

@bernaferrari then they need to be updated to

-keepnames class kotlinx.** { *; }

for kotlinx-coroutines-android

Why?

On Mon, Oct 22, 2018, 5:10 AM Anton Averin <[email protected] wrote:

@bernaferrari https://github.com/bernaferrari then they need to be
updated to

-keepnames class kotlinx.** { *; }

for kotlinx-coroutines-android

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/Kotlin/kotlinx.coroutines/issues/657#issuecomment-431774293,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAEEESZtvZwmEJ_6n71AW3dhWe-e3j4cks5unYt6gaJpZM4XFs_r
.

I have the same issue with 0.30.2

I also get default rule at
https://github.com/Kotlin/kotlinx.coroutines/blob/master/core/kotlinx-coroutines-core/resources/META-INF/proguard/coroutines.pro

Got the same message @trashkalmar

-keepnames class kotlinx.** { *; } did work though

I still have error even though I used suggested ProGuard rules

The suggested proguard rules should be enough. I mean:

# ServiceLoader support
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}

# Most of volatile fields are updated with AFU and should not be mangled
-keepclassmembernames class kotlinx.** {
    volatile <fields>;
}

I was recently facing this issue and realised that it was my fault and nothing to do with the proguard rules. Basically, we were re-signing the apk and removing the META-INF folder in the process. So, for the ones that are still facing the issue, please make sure that you are not doing the same (re-signing your apk and removing the META-INF folder after the release build is done). If that's the case, I would suggest you to generate an unsigned build and sign it afterwards.

Just for reference, I'm using the version 1.0.1.
implementation ("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1")

Hope it helps.

We were having this crash without even using ProGuard 😅 As mentioned by @djrsousa, it's because we were:

Signing the APK twice,

and replacing the META-INF folder in the process...

In our case, we put signingConfigs in the gradle file, then use the Generate Signed Bundle / APK to create the bundle. :D
Removing the signingConfigs solves the problem.

@djrsousa thanks for spelling out the issue so well. Wished I had seen it before spending extra time researching the issue, but it was a good experience nonetheless.
Your suggestions, or moving to letting your build.gradle specify how to sign the app in debug and release modes, work, but if people still want to follow their current re-signing flow, they could delete only few files in the META-INF folder instead of all the files:

zip -d "$apkInputFullPath" META-INF/\*.RSA
zip -d "$apkInputFullPath" META-INF/\*.SF
zip -d "$apkInputFullPath" META-INF/\*.MF

Unless I am missing something, this should do the trick and be a very minimal change to the script people might be already running. Those files are the only ones that get added / modified when the signing occurs from what we could see.

We were having this crash without even using ProGuard 😅 As mentioned by @djrsousa, it's because we were:

Signing the APK twice,

and replacing the META-INF folder in the process...

How can i sign the apk twice,but just replace the signature files in the META-INF folder?
Please... this confused me some days....

Was this page helpful?
0 / 5 - 0 ratings