fix(YouTube): fix potential litho filter thread race

This commit is contained in:
LisoUseInAIKyrios 2023-08-02 15:04:29 +04:00
parent 1c2976526e
commit d3f523f9dd

View File

@ -100,7 +100,7 @@ final class CustomFilterGroup extends StringFilterGroup {
*/
class ByteArrayFilterGroup extends FilterGroup<byte[]> {
private int[][] failurePatterns;
private volatile int[][] failurePatterns;
// Modified implementation from https://stackoverflow.com/a/1507813
private static int indexOf(final byte[] data, final byte[] pattern, final int[] failure) {
@ -143,13 +143,15 @@ class ByteArrayFilterGroup extends FilterGroup<byte[]> {
super(setting, filters);
}
private void buildFailurePatterns() {
private synchronized void buildFailurePatterns() {
if (failurePatterns != null) return; // Thread race and another thread already initialized the search.
LogHelper.printDebug(() -> "Building failure array for: " + this);
failurePatterns = new int[filters.length][];
int[][] failurePatterns = new int[filters.length][];
int i = 0;
for (byte[] pattern : filters) {
failurePatterns[i++] = createFailurePattern(pattern);
}
this.failurePatterns = failurePatterns; // Must set after initialization finishes.
}
@Override
@ -185,7 +187,7 @@ abstract class FilterGroupList<V, T extends FilterGroup<V>> implements Iterable<
/**
* Search graph. Created only if needed.
*/
private TrieSearch<V> search;
private volatile TrieSearch<V> search;
@SafeVarargs
protected final void addAll(final T... groups) {
@ -193,9 +195,11 @@ abstract class FilterGroupList<V, T extends FilterGroup<V>> implements Iterable<
search = null; // Rebuild, if already created.
}
protected final void buildSearch() {
protected final synchronized void buildSearch() {
// Since litho filtering is multi-threaded, this method can be concurrently called by multiple threads.
if (search != null) return; // Thread race and another thread already initialized the search.
LogHelper.printDebug(() -> "Creating prefix search tree for: " + this);
search = createSearchGraph();
TrieSearch<V> search = createSearchGraph();
for (T group : filterGroups) {
if (!group.includeInSearch()) {
continue;
@ -212,6 +216,7 @@ abstract class FilterGroupList<V, T extends FilterGroup<V>> implements Iterable<
});
}
}
this.search = search; // Must set after it's completely initialized.
}
@NonNull