javac index: do not use read-action in myOpenCloseLock otherwise it leads to deadlocks on index#close()

GitOrigin-RevId: fc8af15bb71d20dcf70a1587a66d4e05c1fbc300
This commit is contained in:
Dmitry Batkovich
2021-03-22 19:27:12 +00:00
committed by intellij-monorepo-bot
parent df3ed9824b
commit a21ae5b03c
2 changed files with 32 additions and 29 deletions
@@ -17,6 +17,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
@@ -39,6 +40,7 @@ import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.containers.CollectionFactory;
import com.intellij.util.containers.ConcurrentFactoryMap;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.indexing.StorageException;
import com.intellij.util.messages.MessageBusConnection;
import it.unimi.dsi.fastutil.ints.IntCollection;
@@ -406,16 +408,27 @@ public abstract class CompilerReferenceServiceBase<Reader extends CompilerRefere
}
protected void openReaderIfNeeded(IndexOpenReason reason) {
// do not run read action inside myOpenCloseLock
List<Module> compiledModules = null;
if (reason == IndexOpenReason.COMPILATION_FINISHED) {
compiledModules = ReadAction.nonBlocking(() -> {
if (myProject.isDisposed()) {
return null;
}
final ModuleManager moduleManager = ModuleManager.getInstance(myProject);
return ContainerUtil.map(myDirtyScopeHolder.getCompilationAffectedModules(), moduleManager::findModuleByName);
}).executeSynchronously();
}
myCompilationCount.increment();
myOpenCloseLock.lock();
try {
try {
switch (reason) {
case UP_TO_DATE_CACHE:
myDirtyScopeHolder.upToDateChecked(true);
break;
case COMPILATION_FINISHED:
myDirtyScopeHolder.compilerActivityFinished();
if (reason == IndexOpenReason.COMPILATION_FINISHED) {
myDirtyScopeHolder.compilerActivityFinished(compiledModules);
}
else if (reason == IndexOpenReason.UP_TO_DATE_CACHE) {
myDirtyScopeHolder.upToDateCheckFinished(Module.EMPTY_ARRAY);
}
}
catch (RuntimeException e) {
@@ -433,12 +446,16 @@ public abstract class CompilerReferenceServiceBase<Reader extends CompilerRefere
}
private void markAsOutdated(boolean decrementBuildCount) {
Module[] modules = ReadAction.compute(() -> myProject.isDisposed()
? null
: ModuleManager.getInstance(myProject).getModules());
myOpenCloseLock.lock();
try {
if (decrementBuildCount) {
--myActiveBuilds;
}
myDirtyScopeHolder.upToDateChecked(false);
if (modules == null) return;
myDirtyScopeHolder.upToDateCheckFinished(modules);
} finally {
myOpenCloseLock.unlock();
}
@@ -109,34 +109,20 @@ public class DirtyScopeHolder extends UserDataHolderBase implements AsyncFileLis
}
}
public void upToDateChecked(boolean isUpToDate) {
final Module[] modules = ReadAction.compute(() -> {
final Project project = myService.getProject();
if (project.isDisposed()) {
return null;
}
return ModuleManager.getInstance(project).getModules();
});
if (modules == null) return;
void upToDateCheckFinished(Module @NotNull [] modules) {
compilationFinished(() -> {
if (!isUpToDate) {
ContainerUtil.addAll(myVFSChangedModules, modules);
}
ContainerUtil.addAll(myVFSChangedModules, modules);
});
}
void compilerActivityFinished() {
final List<Module> compiledModules = ReadAction.compute(() -> {
final Project project = myService.getProject();
if (project.isDisposed()) {
return null;
}
final ModuleManager moduleManager = ModuleManager.getInstance(myService.getProject());
return ContainerUtil.map(myCompilationAffectedModules, moduleManager::findModuleByName);
});
@NotNull Set<String> getCompilationAffectedModules() {
return myCompilationAffectedModules;
}
void compilerActivityFinished(List<Module> compiledModules) {
compilationFinished(() -> {
if (compiledModules == null) return;
myVFSChangedModules.removeAll(compiledModules);
compiledModules.forEach(myVFSChangedModules::remove);
});
}