Status Update
Comments
jb...@google.com <jb...@google.com> #2
reemission of the same liveData is racy
kj...@google.com <kj...@google.com>
mk...@google.com <mk...@google.com>
mk...@google.com <mk...@google.com> #3
ga...@google.com <ga...@google.com> #4
sg...@google.com <sg...@google.com> #5
@Test
fun raceTest() {
val subLiveData = MutableLiveData(1)
val subject = liveData(testScope.coroutineContext) {
emitSource(subLiveData)
emitSource(subLiveData) //crashes
}
subject.addObserver().apply {
testScope.advanceUntilIdle()
}
}
ga...@google.com <ga...@google.com> #6
sg...@google.com <sg...@google.com> #7
I actually have a WIP fix for it:
if your case is the one i found (emitting same LiveData multiple times, as shown in #5) you can work around it by adding a dummy transformation.
val subLiveData = MutableLiveData(1)
val subject = liveData(testScope.coroutineContext) {
emitSource(subLiveData.map {it })
emitSource(subLiveData.map {it} )
}
py...@squareup.com <py...@squareup.com> #8
Branch: androidx-master-dev
commit af12e75e6b4110f48e44ca121466943909de8f06
Author: Yigit Boyar <yboyar@google.com>
Date: Tue Sep 03 12:58:11 2019
Fix coroutine livedata race condition
This CL fixes a bug in liveData builder where emitting same
LiveData source twice would make it crash because the second
emission registry could possibly happen before first one is
removed as source.
We fix it by using a suspending dispose function. It does feel
a bit hacky but we cannot make DisposableHandle.dispose async
and we do not want to block there. This does not mean that there
is a problem if developer disposes it manually since our emit
functions take care of making sure it disposes (and there is
no other way to add source to the underlying MediatorLiveData)
Bug: 140249349
Test: BuildLiveDataTest#raceTest_*
Change-Id: I0b464c242a583da4669af195cf2504e2adc4de40
M lifecycle/lifecycle-livedata-ktx/api/2.2.0-alpha05.txt
M lifecycle/lifecycle-livedata-ktx/api/current.txt
M lifecycle/lifecycle-livedata-ktx/api/public_plus_experimental_2.2.0-alpha05.txt
M lifecycle/lifecycle-livedata-ktx/api/public_plus_experimental_current.txt
M lifecycle/lifecycle-livedata-ktx/api/restricted_2.2.0-alpha05.txt
M lifecycle/lifecycle-livedata-ktx/api/restricted_current.txt
M lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/CoroutineLiveData.kt
M lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/BuildLiveDataTest.kt
xa...@google.com <xa...@google.com> #9
I can see how there is indeed a big issue for optional dependencies on libraries (ie library is setup as compileOnly
). We should really find a way to fix this on the AGP side.
sg...@google.com <sg...@google.com> #10
Maybe I am missing something, but shouldn't leakcanary-object-watcher-android-androidx
have a provided
lifecycle
. If I understand correctly a provided
dependency is on classpath for compilation, but the presence at runtime is not through that dependency. Of course the provided
version and the runtime version (if present) must be compatible.
ga...@google.com <ga...@google.com> #11
The issue is that compileOnly
(provided
for Maven) is not added to the desugaring classpath. Each library is dexed separately, and its runtime classpath (api
, implementation
, runtimeOnly
dependencies) are in the desugaring classpath. E.g if library A has compileOnly dep B and implementation dependency C, only C will be in the desugaring classpath (even if B is in the application's runtime classpath).
Some options to tackle this may be:
- detect if some types are missing while desugaring that we are present in the full classpath, and try to desugar again against the full runtime classpath
- add a feature in Gradle to allow dynamic expansion of runtime classpath with compileOnly dependencies that are present in the resolved configuration
As a temporary workaround, you can also specify android.enableDexingArtifactTransform=false
, but please note that this has a build speed impact.
xa...@google.com <xa...@google.com> #12
We should, at the very least, detect that there are compileOnly
dependencies while desugaring is enabled and warn the users about it. Maybe it should even break unless android.enableDexingArtifactTransform
is set to false
.
We can't keep the setup as is, where the generated output is wrong.
ga...@google.com <ga...@google.com> #13
We were emitting warnings for every missing type, but because libraries ship with JVM and android code in the same jar, some types cannot be resolved correctly for code that's unreachable and users were complaining about the noisy logging, so we downgraded to info.
Using compileOnly
is very common for annotation processors, so disabling artifact transforms in this use case may impact significant number of users unnecessarily.
ga...@google.com <ga...@google.com>
il...@google.com <il...@google.com> #14
FWIW, we've added a workaround in the Lifecycle library for this particular problem in
If testing a fix on the AGP side, make sure to Lifecycle 2.5.0-rc01 or earlier to reproduce this crash as we'll silently be working around the incorrectly generated output on later versions.
to...@gmail.com <to...@gmail.com> #15
However, this solution will no longer be available. This is because this option has been deprecated in AGP 8.0 and will be removed in 8.2.
Could you please postpone the removal of the enableDexingArtifactTransform until the desugar issue regarding compileOnly is resolved?
to...@gmail.com <to...@gmail.com> #16
hu...@google.com <hu...@google.com> #17
Could you please postpone the removal of the enableDexingArtifactTransform until the desugar issue regarding compileOnly is resolved?
Yes, we'll need to fix this issue first before removing the property.
This is puzzling, but in my project, if I enable minify in the app module, desugar seems to run fine even with enableDexingArtifactTransform=true.
That's correct, it's because with minifyEnabled = true
we have a different pipeline which doesn't use dexing transforms.
hu...@google.com <hu...@google.com> #18
Update: Starting with AGP 8.3.0-alpha06, the workaround for this issue is to enable the following property in gradle.properties
:
android.useFullClasspathForDexingTransform = true
For more details on this property, please see
We're not enabling this property by default yet because it has some performance overhead and most projects don't need it.
Next steps:
- Measure the performance impact of enabling this property. (Please let us know if it significantly slows down your build.)
- Measure how many projects need to use this property.
hu...@google.com <hu...@google.com> #19
Downgrading this issue to P2 as there is a workaround & we will address this issue in a future release once we have more data (
z-...@unext.jp <z-...@unext.jp> #20
The workaround android.useFullClasspathForDexingTransform = true
breaks baseline profile generation.
You can simply reproduce it in NowInAndroid. Just add android.useFullClasspathForDexingTransform = true
into gradle.properties
and run ./gradlew :app:generateBaselineProfile
.
It will output many errors like this:
Found multiple transforms that can produce a variant of com.caverock:androidsvg-aar:1.4 with requested attributes:
- artifactType 'android-asm-instrumented-jars'
- com.android.build.api.attributes.AgpVersionAttr '8.3.0'
- com.android.build.api.attributes.BuildTypeAttr 'nonMinifiedRelease'
- com.android.build.api.attributes.ProductFlavor:contentType 'demo'
- org.gradle.category 'library'
- org.gradle.jvm.environment 'android'
- org.gradle.usage 'java-runtime'
- org.jetbrains.kotlin.platform.type 'androidJvm'
Found the following transforms:
- From 'com.caverock:androidsvg-aar:1.4 configuration runtime':
- With source attributes:
- artifactType 'aar'
- org.gradle.category 'library'
- org.gradle.libraryelements 'jar'
- org.gradle.status 'release'
- org.gradle.usage 'java-runtime'
- Candidate transform(s):
- Transform 'AarToClassTransform -> AsmClassesTransform' producing attributes:
- artifactType 'android-asm-instrumented-jars'
- asm-transformed-variant 'demoBenchmarkRelease'
- org.gradle.category 'library'
- org.gradle.libraryelements 'jar'
- org.gradle.status 'release'
- org.gradle.usage 'java-runtime'
- Transform 'AarToClassTransform -> AsmClassesTransform' producing attributes:
- artifactType 'android-asm-instrumented-jars'
- asm-transformed-variant 'demoDebug'
- org.gradle.category 'library'
- org.gradle.libraryelements 'jar'
- org.gradle.status 'release'
- org.gradle.usage 'java-runtime'
- Transform 'AarToClassTransform -> AsmClassesTransform' producing attributes:
- artifactType 'android-asm-instrumented-jars'
- asm-transformed-variant 'demoNonMinifiedRelease'
- org.gradle.category 'library'
- org.gradle.libraryelements 'jar'
- org.gradle.status 'release'
- org.gradle.usage 'java-runtime'
- Transform 'AarToClassTransform -> AsmClassesTransform' producing attributes:
- artifactType 'android-asm-instrumented-jars'
- asm-transformed-variant 'demoRelease'
- org.gradle.category 'library'
- org.gradle.libraryelements 'jar'
- org.gradle.status 'release'
- org.gradle.usage 'java-runtime'
- Transform 'AarToClassTransform -> AsmClassesTransform' producing attributes:
- artifactType 'android-asm-instrumented-jars'
- asm-transformed-variant 'prodBenchmarkRelease'
- org.gradle.category 'library'
- org.gradle.libraryelements 'jar'
- org.gradle.status 'release'
- org.gradle.usage 'java-runtime'
- Transform 'AarToClassTransform -> AsmClassesTransform' producing attributes:
- artifactType 'android-asm-instrumented-jars'
- asm-transformed-variant 'prodDebug'
- org.gradle.category 'library'
- org.gradle.libraryelements 'jar'
- org.gradle.status 'release'
- org.gradle.usage 'java-runtime'
- Transform 'AarToClassTransform -> AsmClassesTransform' producing attributes:
- artifactType 'android-asm-instrumented-jars'
- asm-transformed-variant 'prodNonMinifiedRelease'
- org.gradle.category 'library'
- org.gradle.libraryelements 'jar'
- org.gradle.status 'release'
- org.gradle.usage 'java-runtime'
- Transform 'AarToClassTransform -> AsmClassesTransform' producing attributes:
- artifactType 'android-asm-instrumented-jars'
- asm-transformed-variant 'prodRelease'
- org.gradle.category 'library'
- org.gradle.libraryelements 'jar'
- org.gradle.status 'release'
- org.gradle.usage 'java-runtime'
The generation will also be failed if you disable this property due to the crash described in this issue. Any way to fix or avoid this error? If not, could you please upgrade this issue?
hu...@google.com <hu...@google.com> #21
Thanks a lot for letting us know!
I've filed
hu...@google.com <hu...@google.com> #22
cc team for visibility: The android.useFullClasspathForDexingTransform = true
flag (java.lang.AbstractMethodError
issues (e.g.,
Description
Lifecycle: 2.5.0-alpha01 - 2.5.0-beta01
Devices/Android versions reproduced on: Emulator & various tablets 5.0 - 11.
If this is a bug in the library, we would appreciate if you could attach:
Anything with a minsdk under API 24 will cause the crash. So it somehow ties into the Java 8, desugaring, and Kotlin interface default methods I think.
Seehttps://github.com/square/leakcanary/issues/2314 for extra details.