Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ public void thumbnail_onResourceReady_forPrimary_isComplete_whenRequestListenerI
Glide.init(
context,
new GlideBuilder()
.setSourceExecutor(GlideExecutor.newSourceBuilder().setThreadCount(1).build()));
.setSourceExecutor(GlideExecutor.newSourceBuilder().setThreadCount(1).build())
.setFixSingleRequestClearDeadlock(true));

AtomicBoolean isPrimaryRequestComplete = new AtomicBoolean(false);
CountDownLatch countDownLatch = new CountDownLatch(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ public void setUp() {
// Some emulators only have a single resize thread, so waiting on a latch will block them
// forever.
Glide.init(
context, new GlideBuilder().setSourceExecutor(GlideExecutor.newUnlimitedSourceExecutor()));
context,
new GlideBuilder()
.setSourceExecutor(GlideExecutor.newUnlimitedSourceExecutor())
.setFixSingleRequestClearDeadlock(true));
}

@Test
Expand Down
16 changes: 16 additions & 0 deletions library/src/main/java/com/bumptech/glide/GlideBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,19 @@ public GlideBuilder setDisableHardwareBitmapsOnO(boolean disableHardwareBitmapsO
return this;
}

/**
* Fix single request clear deadlock mentioned in <a
* href="https://github.com/bumptech/glide/issues/5617">#5617</a>.
*
* <p>This flag changes {@link com.bumptech.glide.request.SingleRequest} to lock on underlying
* {@link Engine} to avoid deadlocks in calling code that also requires a lock on the {@link
* Engine}.
*/
public GlideBuilder setFixSingleRequestClearDeadlock(boolean isEnabled) {
glideExperimentsBuilder.update(new FixSingleRequestClearDeadlock(), isEnabled);
return this;
}

void setRequestManagerFactory(@Nullable RequestManagerFactory factory) {
this.requestManagerFactory = factory;
}
Expand Down Expand Up @@ -653,4 +666,7 @@ public static final class OverrideGlideThreadPriority implements Experiment {}

/** See {@link #setUseMediaStoreOpenFileApisIfPossible(boolean)}. */
public static final class UseMediaStoreOpenFileApisIfPossible implements Experiment {}

/** See {@link #setFixSingleRequestClearDeadlock(boolean)}. */
public static final class FixSingleRequestClearDeadlock implements Experiment {}
}
10 changes: 9 additions & 1 deletion library/src/main/java/com/bumptech/glide/RequestBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RawRes;
import com.bumptech.glide.GlideBuilder.FixSingleRequestClearDeadlock;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.Transformation;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
Expand Down Expand Up @@ -68,6 +69,7 @@ public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBui
private final Class<TranscodeType> transcodeClass;
private final Glide glide;
private final GlideContext glideContext;
private final GlideExperiments experiments;

@NonNull
@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -99,6 +101,7 @@ protected RequestBuilder(
this.context = context;
this.transitionOptions = requestManager.getDefaultTransitionOptions(transcodeClass);
this.glideContext = glide.getGlideContext();
this.experiments = glide.getGlideContext().getExperiments();

initRequestListeners(requestManager.getDefaultRequestListeners());
apply(requestManager.getDefaultRequestOptions());
Expand Down Expand Up @@ -1166,8 +1169,13 @@ private Request buildRequest(
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> requestOptions,
Executor callbackExecutor) {
GlideExperiments experiments = glideContext.getExperiments();
Object requestLock =
glideContext.getExperiments().isEnabled(FixSingleRequestClearDeadlock.class)
? glideContext.getEngine()
: new Object();
return buildRequestRecursive(
/* requestLock= */ new Object(),
requestLock,
target,
targetListener,
/* parentCoordinator= */ null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.bumptech.glide.GlideBuilder.FixSingleRequestClearDeadlock;
import com.bumptech.glide.GlideContext;
import com.bumptech.glide.GlideExperiments;
import com.bumptech.glide.Priority;
Expand Down Expand Up @@ -1071,6 +1072,8 @@ static final class SingleRequestBuilder {
private final Map<Class<?>, Transformation<?>> transformations = new HashMap<>();

SingleRequestBuilder() {
GlideExperiments glideExperiments = mock(GlideExperiments.class);
when(glideExperiments.isEnabled(FixSingleRequestClearDeadlock.class)).thenReturn(true);
when(glideContext.getExperiments()).thenReturn(mock(GlideExperiments.class));
when(requestCoordinator.getRoot()).thenReturn(requestCoordinator);
when(requestCoordinator.canSetImage(any(Request.class))).thenReturn(true);
Expand Down