Skip to content

Commit 9c70aa5

Browse files
committed
Clear the error request in ErrorRequestCoordinator if it’s running.
Previously we’d never clear the error request which could lead to a StateVerifier exception or an object pooling error because primary.isLoadFailed() would always return false because the state would be reset from failed to cleared in the call to primarly.clear() on the line immediately above the check. Fixes #2767.
1 parent ffd0fe0 commit 9c70aa5

File tree

3 files changed

+40
-2
lines changed

3 files changed

+40
-2
lines changed

instrumentation/src/androidTest/java/com/bumptech/glide/ErrorHandlingTest.java

+27
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,13 @@
2323
import com.bumptech.glide.load.engine.Resource;
2424
import com.bumptech.glide.load.engine.executor.GlideExecutor;
2525
import com.bumptech.glide.load.engine.executor.GlideExecutor.UncaughtThrowableStrategy;
26+
import com.bumptech.glide.request.FutureTarget;
2627
import com.bumptech.glide.request.RequestListener;
2728
import com.bumptech.glide.test.ConcurrencyHelper;
2829
import com.bumptech.glide.test.ResourceIds;
2930
import com.bumptech.glide.test.TearDownGlide;
31+
import com.bumptech.glide.test.WaitModelLoader;
32+
import com.bumptech.glide.test.WaitModelLoader.WaitModel;
3033
import java.io.File;
3134
import java.util.concurrent.CountDownLatch;
3235
import org.junit.Before;
@@ -106,6 +109,30 @@ public void load_whenLoadSucceeds_butEncoderFails_doesNotCallOnLoadFailed()
106109
.onLoadFailed(any(GlideException.class), any(), anyDrawableTarget(), anyBoolean());
107110
}
108111

112+
@Test
113+
public void clearRequest_withError_afterPrimaryFails_clearsErrorRequest()
114+
throws InterruptedException {
115+
WaitModel<Integer> errorModel = WaitModelLoader.Factory.waitOn(ResourceIds.raw.canonical);
116+
117+
FutureTarget<Drawable> target =
118+
Glide.with(context)
119+
.load((Object) null)
120+
.error(
121+
Glide.with(context)
122+
.load(errorModel)
123+
.listener(requestListener))
124+
.submit();
125+
126+
Glide.with(context).clear(target);
127+
errorModel.countDown();
128+
129+
// Make sure any pending requests run.
130+
concurrency.pokeMainThread();
131+
Glide.tearDown();
132+
// Make sure that any callbacks posted back to the main thread run.
133+
concurrency.pokeMainThread();
134+
}
135+
109136
private static final class WaitForErrorStrategy implements UncaughtThrowableStrategy {
110137
final CountDownLatch latch = new CountDownLatch(1);
111138
@Nullable Throwable error = null;

library/src/main/java/com/bumptech/glide/request/ErrorRequestCoordinator.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ public void pause() {
4343
@Override
4444
public void clear() {
4545
primary.clear();
46-
if (primary.isFailed()) {
46+
// Don't check primary.isFailed() here because it will have been reset by the clear call
47+
// immediately before this.
48+
if (error.isRunning()) {
4749
error.clear();
4850
}
4951
}

library/src/test/java/com/bumptech/glide/request/ErrorRequestCoordinatorTest.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,9 @@ public void clear_whenPrimaryHasNotFailed_doesNotClearError() {
8080
}
8181

8282
@Test
83-
public void clear_whenPrimaryHasFailed_clearsError() {
83+
public void clear_whenPrimaryHasFailed_errorIsRunning_clearsError() {
8484
when(primary.isFailed()).thenReturn(true);
85+
when(error.isRunning()).thenReturn(true);
8586
coordinator.clear();
8687
verify(error).clear();
8788
}
@@ -93,6 +94,14 @@ public void clear_whenPrimaryHasFailed_clearsPrimary() {
9394
verify(primary).clear();
9495
}
9596

97+
@Test
98+
public void clear_whenErrorIsRunning_clearsError() {
99+
when(error.isRunning()).thenReturn(true);
100+
coordinator.clear();
101+
102+
verify(error).clear();
103+
}
104+
96105
@Test
97106
public void isPaused_primaryNotFailed_primaryNotPaused_returnsFalse() {
98107
assertThat(coordinator.isPaused()).isFalse();

0 commit comments

Comments
 (0)