pooled thread leak after canceling inspection unexpectedly

This commit is contained in:
Alexey Kudravtsev
2015-11-03 14:29:35 +03:00
parent de8dadeee2
commit 4f5a775b1b
@@ -84,10 +84,7 @@ import java.io.IOException;
import java.io.OutputStreamWriter;
import java.lang.reflect.Constructor;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.*;
public class GlobalInspectionContextImpl extends GlobalInspectionContextBase implements GlobalInspectionContext {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.GlobalInspectionContextImpl");
@@ -389,7 +386,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
final BlockingQueue<PsiFile> filesToInspect = new ArrayBlockingQueue<PsiFile>(1000);
final Queue<PsiFile> filesFailedToInspect = new LinkedBlockingQueue<PsiFile>();
// use original progress indicator here since we don't want it to cancel on write action start
startIterateScope(scope, localScopeFiles, headlessEnvironment, filesToInspect, progressIndicator);
Future<?> future = startIterateScopeInBackground(scope, localScopeFiles, headlessEnvironment, filesToInspect, progressIndicator);
Processor<PsiFile> processor = new Processor<PsiFile>() {
@Override
@@ -410,31 +407,43 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
return true;
}
};
while (true) {
Disposable disposable = Disposer.newDisposable();
ProgressIndicator wrapper = new SensitiveProgressWrapper(progressIndicator);
wrapper.start();
ProgressIndicatorUtils.forceWriteActionPriority(wrapper, disposable);
try {
while (true) {
Disposable disposable = Disposer.newDisposable();
ProgressIndicator wrapper = new SensitiveProgressWrapper(progressIndicator);
wrapper.start();
ProgressIndicatorUtils.forceWriteActionPriority(wrapper, disposable);
try {
// use wrapper here to cancel early when write action start but do not affect the original indicator
((JobLauncherImpl)JobLauncher.getInstance()).processQueue(filesToInspect, filesFailedToInspect, wrapper, TOMBSTONE, processor);
break;
}
catch (ProcessCanceledException ignored) {
progressIndicator.checkCanceled();
// PCE may be thrown from inside wrapper when write action started
// go on with the write and then resume processing the rest of the queue
assert !ApplicationManager.getApplication().isReadAccessAllowed();
assert !ApplicationManager.getApplication().isDispatchThread();
try {
// use wrapper here to cancel early when write action start but do not affect the original indicator
((JobLauncherImpl)JobLauncher.getInstance()).processQueue(filesToInspect, filesFailedToInspect, wrapper, TOMBSTONE, processor);
break;
}
catch (ProcessCanceledException ignored) {
progressIndicator.checkCanceled();
// PCE may be thrown from inside wrapper when write action started
// go on with the write and then resume processing the rest of the queue
assert !ApplicationManager.getApplication().isReadAccessAllowed();
assert !ApplicationManager.getApplication().isDispatchThread();
// wait for write action to complete
ApplicationManager.getApplication().runReadAction(EmptyRunnable.getInstance());
}
finally {
Disposer.dispose(disposable);
// wait for write action to complete
ApplicationManager.getApplication().runReadAction(EmptyRunnable.getInstance());
}
finally {
Disposer.dispose(disposable);
}
}
}
finally {
filesToInspect.clear(); // let background thread a chance to put TOMBSTONE and complete
try {
future.get(30, TimeUnit.SECONDS);
}
catch (Exception e) {
LOG.error(e);
}
}
progressIndicator.checkCanceled();
for (Tools tools : globalSimpleTools) {
@@ -500,12 +509,13 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
private static final PsiFile TOMBSTONE = PsiUtilCore.NULL_PSI_FILE;
private void startIterateScope(@NotNull final AnalysisScope scope,
@Nullable final Collection<VirtualFile> localScopeFiles,
final boolean headlessEnvironment,
@NotNull final BlockingQueue<PsiFile> outFilesToInspect,
@NotNull final ProgressIndicator progressIndicator) {
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@NotNull
private Future<?> startIterateScopeInBackground(@NotNull final AnalysisScope scope,
@Nullable final Collection<VirtualFile> localScopeFiles,
final boolean headlessEnvironment,
@NotNull final BlockingQueue<PsiFile> outFilesToInspect,
@NotNull final ProgressIndicator progressIndicator) {
return ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
try {