mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
platform: fix notBlocking task leaking via Disposer
GitOrigin-RevId: 923f6fcff2438e285a259a82770440ffb21212e7
This commit is contained in:
committed by
intellij-monorepo-bot
parent
a33b82d7c9
commit
14f58cbce4
+32
-27
@@ -423,39 +423,44 @@ public final class NonBlockingReadActionImpl<T> implements NonBlockingReadAction
|
||||
}
|
||||
|
||||
T executeSynchronously() {
|
||||
while (true) {
|
||||
attemptComputation();
|
||||
try {
|
||||
while (true) {
|
||||
attemptComputation();
|
||||
|
||||
if (isCancelled()) {
|
||||
throw new ProcessCanceledException();
|
||||
}
|
||||
if (isDone()) {
|
||||
try {
|
||||
return blockingGet(0, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
catch (TimeoutException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
ProgressIndicatorUtils.checkCancelledEvenWithPCEDisabled(myProgressIndicator);
|
||||
ContextConstraint[] constraints = builder.myConstraints;
|
||||
if (shouldFinishOnEdt() || constraints.length != 0) {
|
||||
Semaphore semaphore = new Semaphore(1);
|
||||
invokeLater(() -> {
|
||||
if (checkObsolete()) {
|
||||
semaphore.up();
|
||||
}
|
||||
else {
|
||||
BaseConstrainedExecution.scheduleWithinConstraints(semaphore::up, null, constraints);
|
||||
}
|
||||
});
|
||||
ProgressIndicatorUtils.awaitWithCheckCanceled(semaphore, myProgressIndicator);
|
||||
if (isCancelled()) {
|
||||
throw new ProcessCanceledException();
|
||||
}
|
||||
if (isDone()) {
|
||||
try {
|
||||
return blockingGet(0, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
catch (TimeoutException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
ProgressIndicatorUtils.checkCancelledEvenWithPCEDisabled(myProgressIndicator);
|
||||
ContextConstraint[] constraints = builder.myConstraints;
|
||||
if (shouldFinishOnEdt() || constraints.length != 0) {
|
||||
Semaphore semaphore = new Semaphore(1);
|
||||
invokeLater(() -> {
|
||||
if (checkObsolete()) {
|
||||
semaphore.up();
|
||||
}
|
||||
else {
|
||||
BaseConstrainedExecution.scheduleWithinConstraints(semaphore::up, null, constraints);
|
||||
}
|
||||
});
|
||||
ProgressIndicatorUtils.awaitWithCheckCanceled(semaphore, myProgressIndicator);
|
||||
if (isCancelled()) {
|
||||
throw new ProcessCanceledException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
cleanupIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean attemptComputation() {
|
||||
|
||||
+26
@@ -256,6 +256,32 @@ public class NonBlockingReadActionTest extends LightPlatformTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testDoNotLeakDisposablesOnCancelledIndicator() {
|
||||
ProgressIndicator outerIndicator = new EmptyProgressIndicator();
|
||||
Disposable disposable = Disposer.newDisposable();
|
||||
try {
|
||||
Future<?> future = ApplicationManager.getApplication().executeOnPooledThread(() -> {
|
||||
assertThrows(ProcessCanceledException.class, () -> {
|
||||
ReadAction.nonBlocking(() -> {
|
||||
outerIndicator.cancel();
|
||||
throw new ProcessCanceledException();
|
||||
})
|
||||
.expireWith(disposable)
|
||||
.wrapProgress(outerIndicator)
|
||||
.executeSynchronously();
|
||||
});
|
||||
});
|
||||
waitForFuture(future);
|
||||
|
||||
Disposer.disposeChildren(disposable, (child) -> {
|
||||
throw new IllegalStateException(child.toString());
|
||||
});
|
||||
}
|
||||
finally {
|
||||
Disposer.dispose(disposable);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSyncExecutionHonorsConstraints() {
|
||||
setupUncommittedDocument();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user