IDEA-132931 ProgressManager does not cancel all threads running under same WrappedProgressIndicator indicator

This commit is contained in:
Alexey Kudravtsev
2014-11-18 13:20:47 +03:00
parent 9c58cac752
commit 5bffb5198d
2 changed files with 39 additions and 12 deletions
@@ -56,7 +56,7 @@ import java.util.concurrent.atomic.AtomicReference;
public class ProgressManagerImpl extends ProgressManager implements Disposable {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.progress.impl.ProgressManagerImpl");
public static final int CHECK_CANCELED_DELAY_MILLIS = 10;
static final int CHECK_CANCELED_DELAY_MILLIS = 10;
private final AtomicInteger myCurrentUnsafeProgressCount = new AtomicInteger(0);
private final AtomicInteger myCurrentModalProgressCount = new AtomicInteger(0);
@@ -321,19 +321,17 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable {
Set<Thread> threads = threadsUnderIndicator.get(indicator);
if (threads != null) {
for (Thread thread : threads) {
ProgressIndicator currentIndicator = getCurrentIndicator(thread);
boolean underCancelledIndicator = currentIndicator == indicator;
if (!underCancelledIndicator && currentIndicator instanceof WrappedProgressIndicator) {
while(currentIndicator instanceof WrappedProgressIndicator) {
ProgressIndicator originalProgressIndicator = ((WrappedProgressIndicator)currentIndicator).getOriginalProgressIndicator();
if (originalProgressIndicator == indicator) {
underCancelledIndicator = true;
break;
}
currentIndicator = originalProgressIndicator;
boolean underCancelledIndicator = false;
for (ProgressIndicator currentIndicator = getCurrentIndicator(thread);
currentIndicator != null;
currentIndicator = currentIndicator instanceof WrappedProgressIndicator ?
((WrappedProgressIndicator)currentIndicator).getOriginalProgressIndicator() : null) {
if (currentIndicator == indicator) {
underCancelledIndicator = true;
break;
}
}
if (underCancelledIndicator) {
threadsUnderCanceledIndicator.add(thread);
}
@@ -22,6 +22,7 @@ import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.progress.*;
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
import com.intellij.openapi.progress.util.ProgressIndicatorUtils;
import com.intellij.openapi.progress.util.ProgressWrapper;
import com.intellij.openapi.progress.util.ReadTask;
import com.intellij.openapi.util.EmptyRunnable;
import com.intellij.openapi.wm.ex.ProgressIndicatorEx;
@@ -373,6 +374,34 @@ public class ProgressIndicatorTest extends LightPlatformTestCase {
}).assertTiming();
}
public void testWrapperIndicatorGotCanceledTooWhenInnerIndicatorHas() {
final ProgressIndicator progress = new ProgressIndicatorBase(){
@Override
protected boolean isCancelable() {
return true;
}
};
try {
ProgressManager.getInstance().executeProcessUnderProgress(new Runnable() {
@Override
public void run() {
assertFalse(ProgressManagerImpl.threadsUnderCanceledIndicator.contains(Thread.currentThread()));
assertTrue(!progress.isCanceled());
progress.cancel();
assertTrue(ProgressManagerImpl.threadsUnderCanceledIndicator.contains(Thread.currentThread()));
assertTrue(progress.isCanceled());
while (true) { // wait for PCE
ProgressManager.checkCanceled();
}
}
}, ProgressWrapper.wrap(progress));
fail("PCE must have been thrown");
}
catch (ProcessCanceledException ignored) {
}
}
private static class ProgressIndicatorStub implements ProgressIndicatorEx {
private volatile boolean myCanceled;