IJPL-149317 Return back reporting of implicit locks.

Turn off this reporting for unit tests, as there are a lot of false positives.

GitOrigin-RevId: f152e08c7020a381003e6082260ea583aedf7d59
This commit is contained in:
Lev Serebryakov
2024-09-20 15:11:46 +02:00
committed by intellij-monorepo-bot
parent 5a78934da2
commit 2f91af6cb3
4 changed files with 85 additions and 8 deletions

View File

@@ -6244,6 +6244,8 @@ f:com.intellij.util.concurrency.ThreadingAssertions
- s:assertReadAccess():V
- s:assertWriteAccess():V
- s:assertWriteIntentReadAccess():V
- s:isImplicitLockOnEDT():Z
- s:setImplicitLockOnEDT(Z):V
- s:softAssertBackgroundThread():V
- s:softAssertEventDispatchThread():V
- s:softAssertReadAccess():V

View File

@@ -1,6 +1,7 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.util.concurrency;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diagnostic.RuntimeExceptionWithAttachments;
@@ -32,12 +33,16 @@ public final class ThreadingAssertions {
@VisibleForTesting
public static final String MUST_EXECUTE_IN_READ_ACTION =
"Read access is allowed from inside read-action only (see Application.runReadAction())";
private static final String MUST_EXECUTE_IN_READ_ACTION_EXPLICIT =
"Read access is allowed from inside explicit read-action only (see Application.runReadAction()). Now implicit WriteIntentReadAction.run() is used.";
@Internal
@VisibleForTesting
public static final String MUST_NOT_EXECUTE_IN_READ_ACTION =
"Must not execute inside read action";
private static final String MUST_EXECUTE_IN_WRITE_INTENT_READ_ACTION =
"Access is allowed from write thread only";
private static final String MUST_EXECUTE_IN_WRITE_INTENT_READ_ACTION_EXPLICIT =
"Access is allowed from write thread only with explicit WriteIntentReadAction.run(). Now implicit WriteIntentReadAction.run() is used.";
@Internal
@VisibleForTesting
public static final String MUST_EXECUTE_IN_WRITE_ACTION =
@@ -53,6 +58,8 @@ public final class ThreadingAssertions {
private static final String DOCUMENTATION_URL = "https://jb.gg/ij-platform-threading";
private static boolean implicitLock = false;
/**
* Asserts that the current thread is the event dispatch thread.
*
@@ -111,6 +118,17 @@ public final class ThreadingAssertions {
if (!ApplicationManager.getApplication().isReadAccessAllowed()) {
throwThreadAccessException(MUST_EXECUTE_IN_READ_ACTION);
}
else if (isImplicitLockOnEDT() && !ApplicationManager.getApplication().isUnitTestMode()) {
reportImplicitRead();
}
}
/**
* Reports message about implicit read to logger at error level
*/
@Internal
public static void reportImplicitRead() {
getLogger().error(createThreadAccessException(MUST_EXECUTE_IN_READ_ACTION_EXPLICIT));
}
/**
@@ -148,6 +166,17 @@ public final class ThreadingAssertions {
if (!ApplicationManager.getApplication().isWriteIntentLockAcquired()) {
throwWriteIntentReadAccess();
}
else if (isImplicitLockOnEDT()) {
reportImplicitWriteIntent();
}
}
/**
* Reports message about implicit read to logger at error level
*/
@Internal
public static void reportImplicitWriteIntent() {
getLogger().error(createThreadAccessException(MUST_EXECUTE_IN_WRITE_INTENT_READ_ACTION_EXPLICIT));
}
/**
@@ -188,4 +217,20 @@ public final class ThreadingAssertions {
private static @NotNull String describe(@Nullable Thread o) {
return o == null ? "null" : o + " " + System.identityHashCode(o);
}
public static boolean isImplicitLockOnEDT() {
if (!EDT.isCurrentThreadEdt())
return false;
Application app = ApplicationManager.getApplication();
// Don't report implicit locks for unit tests, too many false positives
if (app != null && app.isUnitTestMode())
return false;
return implicitLock;
}
public static void setImplicitLockOnEDT(boolean implicitLock) {
if (!EDT.isCurrentThreadEdt())
return;
ThreadingAssertions.implicitLock = implicitLock;
}
}

View File

@@ -1041,7 +1041,14 @@ internal fun performActivity(e: AWTEvent, needWIL: Boolean, runnable: () -> Unit
else {
val runnableWithWIL =
if (needWIL) {
{ WriteIntentReadAction.run(runnable) }
{
ThreadingAssertions.setImplicitLockOnEDT(true)
try {
WriteIntentReadAction.run(runnable)
} finally {
ThreadingAssertions.setImplicitLockOnEDT(false)
}
}
}
else {
runnable

View File

@@ -81,10 +81,13 @@ internal object AnyThreadWriteThreadingSupport: ThreadingSupport {
is WriteIntentPermit, is WritePermit -> release = false
}
val prevImplicitLock = ThreadingAssertions.isImplicitLockOnEDT()
try {
ThreadingAssertions.setImplicitLockOnEDT(false)
return computation.compute()
}
finally {
ThreadingAssertions.setImplicitLockOnEDT(prevImplicitLock)
if (release) {
ts.release()
}
@@ -221,10 +224,17 @@ internal object AnyThreadWriteThreadingSupport: ThreadingSupport {
fireBeforeReadActionStart(clazz)
val ts = myState.get()
if (ts.hasPermit) {
fireReadActionStarted(clazz)
val rv = block.compute()
fireReadActionFinished(clazz)
return rv
val prevImplicitLock = ThreadingAssertions.isImplicitLockOnEDT()
ThreadingAssertions.setImplicitLockOnEDT(false)
try {
fireReadActionStarted(clazz)
val rv = block.compute()
fireReadActionFinished(clazz)
return rv
}
finally {
ThreadingAssertions.setImplicitLockOnEDT(prevImplicitLock)
}
}
else {
ts.permit = tryGetReadPermit()
@@ -256,6 +266,8 @@ internal object AnyThreadWriteThreadingSupport: ThreadingSupport {
} while (ts.permit == null)
}
}
val prevImplicitLock = ThreadingAssertions.isImplicitLockOnEDT()
ThreadingAssertions.setImplicitLockOnEDT(false)
try {
fireReadActionStarted(clazz)
val rv = block.compute()
@@ -263,6 +275,7 @@ internal object AnyThreadWriteThreadingSupport: ThreadingSupport {
return rv
}
finally {
ThreadingAssertions.setImplicitLockOnEDT(prevImplicitLock)
ts.release()
fireAfterReadActionFinished(clazz)
}
@@ -272,9 +285,16 @@ internal object AnyThreadWriteThreadingSupport: ThreadingSupport {
override fun tryRunReadAction(action: Runnable): Boolean {
val ts = myState.get()
if (ts.hasPermit) {
fireReadActionStarted(action.javaClass)
action.run()
fireReadActionFinished(action.javaClass)
val prevImplicitLock = ThreadingAssertions.isImplicitLockOnEDT()
ThreadingAssertions.setImplicitLockOnEDT(false)
try {
fireReadActionStarted(action.javaClass)
action.run()
fireReadActionFinished(action.javaClass)
}
finally {
ThreadingAssertions.setImplicitLockOnEDT(prevImplicitLock)
}
return true
}
else {
@@ -283,6 +303,8 @@ internal object AnyThreadWriteThreadingSupport: ThreadingSupport {
if (!ts.hasPermit) {
return false
}
val prevImplicitLock = ThreadingAssertions.isImplicitLockOnEDT()
ThreadingAssertions.setImplicitLockOnEDT(false)
try {
fireReadActionStarted(action.javaClass)
action.run()
@@ -290,6 +312,7 @@ internal object AnyThreadWriteThreadingSupport: ThreadingSupport {
return true
}
finally {
ThreadingAssertions.setImplicitLockOnEDT(prevImplicitLock)
ts.release()
fireAfterReadActionFinished(action.javaClass)
}