on project dispose remove all relevant tasks from DocCommitThread queue to fix IDEA-165879 Unguarded section in DocumentCommitThread that leads to spontaneous assertion

This commit is contained in:
Alexey Kudravtsev
2017-02-09 13:42:42 +03:00
parent aef38eb8c0
commit 72f05c4631
2 changed files with 24 additions and 8 deletions
@@ -63,10 +63,7 @@ import org.jetbrains.ide.PooledThreadExecutor;
import javax.swing.*;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
@@ -113,7 +110,7 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi
enable("Listener installed, started");
}
});
});
}
@Override
@@ -949,4 +946,21 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi
return lock != null ? lock : ((UserDataHolderEx)document).putUserDataIfAbsent(DOCUMENT_LOCK, new ReentrantLock());
}
private static final Key<Lock> DOCUMENT_LOCK = Key.create("DOCUMENT_LOCK");
void cancelTasksOnProjectDispose(@NotNull final Project project) {
synchronized (lock) {
cancelTasksOnProjectDispose(project, documentsToCommit);
cancelTasksOnProjectDispose(project, documentsToApplyInEDT);
}
}
private void cancelTasksOnProjectDispose(@NotNull Project project, @NotNull HashSetQueue<CommitTask> queue) {
for (HashSetQueue.PositionalIterator<CommitTask> iterator = queue.iterator(); iterator.hasNext(); ) {
CommitTask commitTask = iterator.next();
if (commitTask.project == project) {
iterator.remove();
commitTask.cancel("project is disposed", this);
}
}
}
}
@@ -33,6 +33,7 @@ import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectLocator;
import com.intellij.openapi.project.impl.ProjectImpl;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.core.impl.PomModelImpl;
@@ -66,20 +67,21 @@ public class PsiDocumentManagerImpl extends PsiDocumentManagerBase implements Se
super(project, psiManager, bus, documentCommitThread);
myDocumentCommitThread = documentCommitThread;
editorFactory.getEventMulticaster().addDocumentListener(this, project);
MessageBusConnection busConnection = bus.connect();
busConnection.subscribe(AppTopics.FILE_DOCUMENT_SYNC, new FileDocumentManagerAdapter() {
MessageBusConnection connection = bus.connect();
connection.subscribe(AppTopics.FILE_DOCUMENT_SYNC, new FileDocumentManagerAdapter() {
@Override
public void fileContentLoaded(@NotNull final VirtualFile virtualFile, @NotNull Document document) {
PsiFile psiFile = ReadAction.compute(() -> myProject.isDisposed() || !virtualFile.isValid() ? null : getCachedPsiFile(virtualFile));
fireDocumentCreated(document, psiFile);
}
});
busConnection.subscribe(DocumentBulkUpdateListener.TOPIC, new DocumentBulkUpdateListener.Adapter() {
connection.subscribe(DocumentBulkUpdateListener.TOPIC, new DocumentBulkUpdateListener.Adapter() {
@Override
public void updateFinished(@NotNull Document doc) {
documentCommitThread.commitAsynchronously(project, doc, "Bulk update finished", ApplicationManager.getApplication().getDefaultModalityState());
}
});
Disposer.register(project, () -> ((DocumentCommitThread)myDocumentCommitThread).cancelTasksOnProjectDispose(project));
}
@Nullable