mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
fix leaks via NonBlockingReadAction#coalesceBy: don't remember tasks if they're already canceled and won't be removed
GitOrigin-RevId: 1242ef740e36ff8364160264fcce567c70b4cd81
This commit is contained in:
committed by
intellij-monorepo-bot
parent
1634ff5860
commit
81d6e89f6c
+7
-1
@@ -229,7 +229,7 @@ public class NonBlockingReadActionImpl<T>
|
||||
}
|
||||
|
||||
private void scheduleReplacementIfAny() {
|
||||
if (myReplacement == null) {
|
||||
if (myReplacement == null || myReplacement.promise.isDone()) {
|
||||
ourTasksByEquality.remove(myCoalesceEquality, this);
|
||||
} else {
|
||||
ourTasksByEquality.put(myCoalesceEquality, myReplacement);
|
||||
@@ -239,6 +239,8 @@ public class NonBlockingReadActionImpl<T>
|
||||
|
||||
void submitOrScheduleCoalesced(@NotNull List<Object> coalesceEquality) {
|
||||
synchronized (ourTasksByEquality) {
|
||||
if (promise.isDone()) return;
|
||||
|
||||
NonBlockingReadActionImpl<?>.Submission current = ourTasksByEquality.get(coalesceEquality);
|
||||
if (current == null) {
|
||||
ourTasksByEquality.put(coalesceEquality, this);
|
||||
@@ -441,4 +443,8 @@ public class NonBlockingReadActionImpl<T>
|
||||
}
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
static Map<List<Object>, NonBlockingReadActionImpl<?>.Submission> getTasksByEquality() {
|
||||
return ourTasksByEquality;
|
||||
}
|
||||
}
|
||||
|
||||
+26
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.openapi.application.impl;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.NonBlockingReadAction;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
@@ -10,8 +11,10 @@ import com.intellij.openapi.editor.impl.DocumentImpl;
|
||||
import com.intellij.openapi.progress.EmptyProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.testFramework.LeakHunter;
|
||||
import com.intellij.testFramework.LightPlatformTestCase;
|
||||
import com.intellij.util.concurrency.AppExecutorUtil;
|
||||
import com.intellij.util.concurrency.Semaphore;
|
||||
@@ -176,4 +179,27 @@ public class NonBlockingReadActionTest extends LightPlatformTestCase {
|
||||
}
|
||||
waitForPromise(promise);
|
||||
}
|
||||
|
||||
public void testDoNotLeakFirstCancelledCoalescedAction() {
|
||||
Object leak = new Object(){};
|
||||
Disposable disposable = Disposer.newDisposable();
|
||||
Disposer.dispose(disposable);
|
||||
CancellablePromise<String> p = ReadAction
|
||||
.nonBlocking(() -> "a")
|
||||
.expireWith(disposable)
|
||||
.coalesceBy(leak)
|
||||
.submit(AppExecutorUtil.getAppExecutorService());
|
||||
assertTrue(p.isCancelled());
|
||||
LeakHunter.checkLeak(NonBlockingReadActionImpl.getTasksByEquality(), leak.getClass());
|
||||
}
|
||||
|
||||
public void testDoNotLeakSecondCancelledCoalescedAction() {
|
||||
Object leak = new Object(){};
|
||||
CancellablePromise<String> p = ReadAction.nonBlocking(() -> "a").coalesceBy(leak).submit(AppExecutorUtil.getAppExecutorService());
|
||||
WriteAction.run(() -> {
|
||||
ReadAction.nonBlocking(() -> "b").coalesceBy(leak).submit(AppExecutorUtil.getAppExecutorService()).cancel();
|
||||
});
|
||||
assertTrue(p.isDone());
|
||||
LeakHunter.checkLeak(NonBlockingReadActionImpl.getTasksByEquality(), leak.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user