Skip to content

Commit

Permalink
Fix obscure 'Main dispatcher is missing' (#4104)
Browse files Browse the repository at this point in the history
For desktop applications, Swing/JavaFx dispatcher should be picked by our fast SL mechanism. But if there is a dependency on firebase-sdk, it breaks: the dependency repackages Android classes, and we incorrectly assume we are on Android platform.

Explicitly take it into account

Fixes #3914
  • Loading branch information
qwwdfsad authored Apr 22, 2024
1 parent fc01633 commit 2bf5930
Showing 1 changed file with 14 additions and 2 deletions.
16 changes: 14 additions & 2 deletions kotlinx-coroutines-core/jvm/src/internal/FastServiceLoader.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ internal object FastServiceLoader {
* If lookups are successful, we return resultinAg instances because we know that
* `MainDispatcherFactory` API is internal and this is the only possible classes of `MainDispatcherFactory` Service on Android.
*
* Such intricate dance is required to avoid calls to `ServiceLoader.load` for multiple reasons:
* Such an intricate dance is required to avoid calls to `ServiceLoader.load` for multiple reasons:
* 1) It eliminates disk lookup on potentially slow devices on the Main thread.
* 2) Various Android toolchain versions by various vendors don't tend to handle ServiceLoader calls properly.
* Sometimes META-INF is removed from the resulting APK, sometimes class names are mangled, etc.
Expand All @@ -51,9 +51,21 @@ internal object FastServiceLoader {
return load(clz, clz.classLoader)
}

/*
* If `ANDROID_DETECTED` is true, it is still possible to have `AndroidDispatcherFactory` missing.
* The most notable case of it is firebase-sdk that repackages some Android classes but can be used from an arbitrary
* K/JVM application.
* See also #3914.
*/
return try {
val result = ArrayList<MainDispatcherFactory>(2)
createInstanceOf(clz, "kotlinx.coroutines.android.AndroidDispatcherFactory")?.apply { result.add(this) }
val mainFactory = createInstanceOf(clz, "kotlinx.coroutines.android.AndroidDispatcherFactory")
if (mainFactory == null) {
// Fallback to regular service loading
return load(clz, clz.classLoader)
}
result.add(mainFactory)
// Also search for test-module factory
createInstanceOf(clz, "kotlinx.coroutines.test.internal.TestMainDispatcherFactory")?.apply { result.add(this) }
result
} catch (e: Throwable) {
Expand Down

0 comments on commit 2bf5930

Please sign in to comment.