Skip to content

Commit 2bf5930

Browse files
authored
Fix obscure 'Main dispatcher is missing' (#4104)
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
1 parent fc01633 commit 2bf5930

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

kotlinx-coroutines-core/jvm/src/internal/FastServiceLoader.kt

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ internal object FastServiceLoader {
3535
* If lookups are successful, we return resultinAg instances because we know that
3636
* `MainDispatcherFactory` API is internal and this is the only possible classes of `MainDispatcherFactory` Service on Android.
3737
*
38-
* Such intricate dance is required to avoid calls to `ServiceLoader.load` for multiple reasons:
38+
* Such an intricate dance is required to avoid calls to `ServiceLoader.load` for multiple reasons:
3939
* 1) It eliminates disk lookup on potentially slow devices on the Main thread.
4040
* 2) Various Android toolchain versions by various vendors don't tend to handle ServiceLoader calls properly.
4141
* Sometimes META-INF is removed from the resulting APK, sometimes class names are mangled, etc.
@@ -51,9 +51,21 @@ internal object FastServiceLoader {
5151
return load(clz, clz.classLoader)
5252
}
5353

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

0 commit comments

Comments
 (0)