[indexes] fixed deadlock in JavaModuleSearcher

GitOrigin-RevId: 3fb26dd08db7770df4063715195a2beb5bd1eb76
This commit is contained in:
Ruslan Cheremin
2025-05-19 18:26:03 +00:00
committed by intellij-monorepo-bot
parent acf6959d1f
commit 896942196e
@@ -5,6 +5,7 @@ import com.intellij.psi.PsiJavaModule;
import com.intellij.psi.impl.java.stubs.index.JavaStubIndexKeys;
import com.intellij.psi.search.searches.JavaModuleSearch;
import com.intellij.psi.stubs.StubIndex;
import com.intellij.util.CommonProcessors.CollectProcessor;
import com.intellij.util.Processor;
import com.intellij.util.QueryExecutor;
import org.jetbrains.annotations.NotNull;
@@ -16,15 +17,29 @@ public final class JavaModuleSearcher implements QueryExecutor<PsiJavaModule, Ja
String name = queryParameters.getName();
StubIndex index = StubIndex.getInstance();
if (name == null) {
return index.processAllKeys(JavaStubIndexKeys.MODULE_NAMES, moduleName -> {
return index.processElements(JavaStubIndexKeys.MODULE_NAMES,
moduleName,
queryParameters.getProject(),
queryParameters.getScope(),
null,
PsiJavaModule.class,
consumer);
}, queryParameters.getScope());
//It is important to collect moduleNames first, then process the name -- don't do it recursively! -- it risks
// a deadlock: processAllKeys() acquires readLock, but processElements() _could_ acquire writeLock (see
// StubIndexEx.tryFixIndexesForProblemFiles())
//In general: it is a bad idea to do recursive index lookups, i.e., another lookup from the lambda passed to something
// like processAllKeys()/processElements(). Such lambdas should be a short & simple code, not complex deep-stack processing.
// In a second case -- 'unfold' the recursive processing, as it is done here.
CollectProcessor<String> moduleNamesCollector = new CollectProcessor<>();
index.processAllKeys(JavaStubIndexKeys.MODULE_NAMES, moduleNamesCollector, queryParameters.getScope());
for (String moduleName : moduleNamesCollector.getResults()) {
boolean shouldContinue = index.processElements(
JavaStubIndexKeys.MODULE_NAMES,
moduleName,
queryParameters.getProject(),
queryParameters.getScope(),
null,
PsiJavaModule.class,
consumer
);
if (!shouldContinue) {
return false;
}
}
return true;
}
return index.processElements(JavaStubIndexKeys.MODULE_NAMES,
name,