Fixed
Status Update
Comments
se...@google.com <se...@google.com> #2
Yigit, do you have time to fix it?
reemission of the same liveData is racy
reemission of the same liveData is racy
se...@google.com <se...@google.com> #3
yea i'll take it.
yb...@google.com <yb...@google.com> #4
Thanks for the detailed analysis. This may not be an issue anymore since we've started using Main.immediate there but I' not sure; I'll try to create a test case.
se...@google.com <se...@google.com> #5
just emitting same live data reproduces the issue.
@Test
fun raceTest() {
val subLiveData = MutableLiveData(1)
val subject = liveData(testScope.coroutineContext) {
emitSource(subLiveData)
emitSource(subLiveData) //crashes
}
subject.addObserver().apply {
testScope.advanceUntilIdle()
}
}
@Test
fun raceTest() {
val subLiveData = MutableLiveData(1)
val subject = liveData(testScope.coroutineContext) {
emitSource(subLiveData)
emitSource(subLiveData) //crashes
}
subject.addObserver().apply {
testScope.advanceUntilIdle()
}
}
ch...@beyls.net <ch...@beyls.net> #6
With 2.2.0-alpha04 (that use Main.immediate), the issue seems to be still there (I tested it by calling emitSource() twice, like your test case)
ne...@gmail.com <ne...@gmail.com> #7
yea sorry immediate does not fix it.
I actually have a WIP fix for it:
https://android-review.googlesource.com/c/platform/frameworks/support/+/1112186
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} )
}
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} )
}
m....@gmail.com <m....@gmail.com> #8
Project: platform/frameworks/support
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
https://android-review.googlesource.com/1112186
https://goto.google.com/android-sha1/af12e75e6b4110f48e44ca121466943909de8f06
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
yb...@google.com <yb...@google.com>
yb...@google.com <yb...@google.com>
ap...@google.com <ap...@google.com> #9
Project: platform/frameworks/support
Branch: androidx-master-dev
commit bab31cacd4ae98057b694f6ae4c781f5f25ee0c9
Author: Yigit Boyar <yboyar@google.com>
Date: Wed Oct 31 23:41:00 2018
Fix live data observe forever in room
This CL fixes a problem where if DAO returned LiveData is
observed with observeForever but there are no references
to the LiveData, it would eventually be garbage collected.
To avoid this, InvalidationTracker now manages these LiveData
objects and strongly references them as long as there is an
active observer.
To be 100%, we should actually do it when LiveData has observers
but right now that API does not exist in the LiveData side
to get notified when the observer count changes 0 and 1.
I've also cleaned up some test code to avoid duplicating the
test observers in each test.
I've also added an integration test that uses room w/o any of
the optional dependencies to ensure that we don't break the
contract on compileOnly dependencies.
Bug: 74477406
Test: LiveDataQueryTest, InvalidationTrackerTest, NoAppCompatTestApp
Change-Id: If88114306d7e20ddaed0312a1203a0d14b710145
M arch/core-testing/src/main/java/androidx/arch/core/executor/TaskExecutorWithFakeMainThread.java
M room/compiler/src/main/kotlin/androidx/room/solver/query/result/LiveDataQueryResultBinder.kt
M room/compiler/src/test/data/daoWriter/output/ComplexDao.java
A room/integration-tests/noappcompattestapp/.gitignore
A room/integration-tests/noappcompattestapp/README.md
A room/integration-tests/noappcompattestapp/build.gradle
A room/integration-tests/noappcompattestapp/src/androidTest/java/androidx/room/integration/noappcompat/BareDatabaseTest.java
A room/integration-tests/noappcompattestapp/src/main/AndroidManifest.xml
A room/integration-tests/noappcompattestapp/src/main/java/androidx/room/integration/noappcompat/BareDatabase.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/paging/DataSourceFactoryTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/InvalidationTrackerTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/LiveDataQueryTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/QueryTransactionTest.java
A room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/TestLifecycleOwner.java
A room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/TestObserver.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/TestUtil.java
M room/runtime/build.gradle
A room/runtime/src/main/java/androidx/room/InvalidationLiveDataContainer.java
M room/runtime/src/main/java/androidx/room/InvalidationTracker.java
A room/runtime/src/main/java/androidx/room/RoomTrackingLiveData.java
A room/runtime/src/test/java/androidx/room/InvalidationLiveDataContainerTest.kt
M room/runtime/src/test/java/androidx/room/InvalidationTrackerTest.java
M settings.gradle
https://android-review.googlesource.com/810053
https://goto.google.com/android-sha1/bab31cacd4ae98057b694f6ae4c781f5f25ee0c9
Branch: androidx-master-dev
commit bab31cacd4ae98057b694f6ae4c781f5f25ee0c9
Author: Yigit Boyar <yboyar@google.com>
Date: Wed Oct 31 23:41:00 2018
Fix live data observe forever in room
This CL fixes a problem where if DAO returned LiveData is
observed with observeForever but there are no references
to the LiveData, it would eventually be garbage collected.
To avoid this, InvalidationTracker now manages these LiveData
objects and strongly references them as long as there is an
active observer.
To be 100%, we should actually do it when LiveData has observers
but right now that API does not exist in the LiveData side
to get notified when the observer count changes 0 and 1.
I've also cleaned up some test code to avoid duplicating the
test observers in each test.
I've also added an integration test that uses room w/o any of
the optional dependencies to ensure that we don't break the
contract on compileOnly dependencies.
Bug: 74477406
Test: LiveDataQueryTest, InvalidationTrackerTest, NoAppCompatTestApp
Change-Id: If88114306d7e20ddaed0312a1203a0d14b710145
M arch/core-testing/src/main/java/androidx/arch/core/executor/TaskExecutorWithFakeMainThread.java
M room/compiler/src/main/kotlin/androidx/room/solver/query/result/LiveDataQueryResultBinder.kt
M room/compiler/src/test/data/daoWriter/output/ComplexDao.java
A room/integration-tests/noappcompattestapp/.gitignore
A room/integration-tests/noappcompattestapp/README.md
A room/integration-tests/noappcompattestapp/build.gradle
A room/integration-tests/noappcompattestapp/src/androidTest/java/androidx/room/integration/noappcompat/BareDatabaseTest.java
A room/integration-tests/noappcompattestapp/src/main/AndroidManifest.xml
A room/integration-tests/noappcompattestapp/src/main/java/androidx/room/integration/noappcompat/BareDatabase.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/paging/DataSourceFactoryTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/InvalidationTrackerTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/LiveDataQueryTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/QueryTransactionTest.java
A room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/TestLifecycleOwner.java
A room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/TestObserver.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/TestUtil.java
M room/runtime/build.gradle
A room/runtime/src/main/java/androidx/room/InvalidationLiveDataContainer.java
M room/runtime/src/main/java/androidx/room/InvalidationTracker.java
A room/runtime/src/main/java/androidx/room/RoomTrackingLiveData.java
A room/runtime/src/test/java/androidx/room/InvalidationLiveDataContainerTest.kt
M room/runtime/src/test/java/androidx/room/InvalidationTrackerTest.java
M settings.gradle
yb...@google.com <yb...@google.com>
yb...@google.com <yb...@google.com> #10
FYI this requires client to update to Room 2.1.0-alpha03 but it is fully compatible with 1.x that WM uses.
yb...@google.com <yb...@google.com> #11
actually it won't work because the change is in generated code. I'll try to backport itinto WM.
ap...@google.com <ap...@google.com> #13
Project: platform/frameworks/support
Branch: androidx-master-dev
commit 3fb46bd8602faaf9c34aa969f8ae589c251c2f72
Author: Yigit Boyar <yboyar@google.com>
Date: Fri Nov 30 13:19:34 2018
Track LiveData returned by the WM
This CL works around a bug in Room 1.x where LiveData returned
by Room might be garbage collected.
Now work manager tracks any live data it returns as long as the
LiveData is active.
Bug: 74477406
Test: ObserForeverTest, WorkManagerLiveDataTrackerTest
Change-Id: I1e45dade1e8a3c29d6c35f7cb0c6e072c68ee658
A work/workmanager/src/androidTest/java/androidx/work/impl/ObserveForeverTest.java
M work/workmanager/src/main/java/androidx/work/impl/WorkManagerImpl.java
A work/workmanager/src/main/java/androidx/work/impl/WorkManagerLiveDataTracker.java
A work/workmanager/src/test/java/androidx/work/impl/WorkManagerLiveDataTrackerTest.java
https://android-review.googlesource.com/838833
https://goto.google.com/android-sha1/3fb46bd8602faaf9c34aa969f8ae589c251c2f72
Branch: androidx-master-dev
commit 3fb46bd8602faaf9c34aa969f8ae589c251c2f72
Author: Yigit Boyar <yboyar@google.com>
Date: Fri Nov 30 13:19:34 2018
Track LiveData returned by the WM
This CL works around a bug in Room 1.x where LiveData returned
by Room might be garbage collected.
Now work manager tracks any live data it returns as long as the
LiveData is active.
Bug: 74477406
Test: ObserForeverTest, WorkManagerLiveDataTrackerTest
Change-Id: I1e45dade1e8a3c29d6c35f7cb0c6e072c68ee658
A work/workmanager/src/androidTest/java/androidx/work/impl/ObserveForeverTest.java
M work/workmanager/src/main/java/androidx/work/impl/WorkManagerImpl.java
A work/workmanager/src/main/java/androidx/work/impl/WorkManagerLiveDataTracker.java
A work/workmanager/src/test/java/androidx/work/impl/WorkManagerLiveDataTrackerTest.java
Description
repro steps from the developer:
launch the app on a device, press the button to update the counters. Then after you use "force gc" from android monitor, the second counter will stop updating
Looks like because nothing keeps a reference to the AlwaysOnLifecycle or the LiveData, both end up being GC'ed. Before it was a single instance so it didn't get GC'ed.
We probably need to keep AlwaysOnLifecycle in memory as long as it has an observer.