IJPL-164171 log coroutine dump as warn if write action cannot be executed in 10 seconds

(cherry picked from commit f7879bcfd40a7d5942fcf4c6db2ea7c7aa955034)

IJ-CR-147194

GitOrigin-RevId: 262f5aeda102a12cdd8267c1066a2acfa7d61d4c
This commit is contained in:
Vladimir Krivosheev
2024-10-19 10:09:30 +02:00
committed by intellij-monorepo-bot
parent c3e401de32
commit cfb1784c09

View File

@@ -2,20 +2,20 @@
package com.intellij.openapi.application
import com.intellij.concurrency.currentThreadContext
import com.intellij.diagnostic.dumpCoroutines
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.progress.blockingContext
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Computable
import com.intellij.openapi.util.IntellijInternalApi
import com.intellij.openapi.util.ThrowableComputable
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asContextElement
import kotlinx.coroutines.withContext
import kotlinx.coroutines.*
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.annotations.ApiStatus.Experimental
import org.jetbrains.annotations.ApiStatus.Internal
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.coroutineContext
import kotlin.time.Duration.Companion.seconds
/**
* Suspends until it's possible to obtain the read lock and then
@@ -258,6 +258,13 @@ fun CoroutineContext.isBackgroundWriteAction(): Boolean =
private val useBackgroundWriteAction = System.getProperty("idea.background.write.action.enabled", "false").toBoolean()
internal fun isBackgroundWriteActionPossible(contextModality: ModalityState?): Boolean {
if (!useBackgroundWriteAction) {
return false
}
return contextModality == null || contextModality == ModalityState.nonModal()
}
/**
* Runs given [action] under [write lock][com.intellij.openapi.application.Application.runWriteAction].
*
@@ -278,18 +285,27 @@ private val useBackgroundWriteAction = System.getProperty("idea.background.write
@ApiStatus.Obsolete
@Internal
suspend fun <T> backgroundWriteAction(action: () -> T): T {
if (useBackgroundWriteAction) {
val contextModality = coroutineContext.contextModality()
if (contextModality == null || contextModality == ModalityState.nonModal()) {
return withContext(Dispatchers.Default + RunInBackgroundWriteActionMarker) {
blockingContext {
ApplicationManager.getApplication().runWriteAction(Computable(action))
}
}
}
val isBackgroundActionAllowed = isBackgroundWriteActionPossible(coroutineContext.contextModality())
val context = if (isBackgroundActionAllowed) {
Dispatchers.Default + RunInBackgroundWriteActionMarker
}
else {
Dispatchers.EDT
}
return writeAction(action)
return withContext(context) {
val dumpJob = if (isBackgroundActionAllowed) launch {
delay(10.seconds)
logger<ApplicationManager>().warn("Cannot execute write action in 10 seconds: ${dumpCoroutines()}")
} else null
try {
@Suppress("ForbiddenInSuspectContextMethod")
ApplicationManager.getApplication().runWriteAction(ThrowableComputable(action))
}
finally {
dumpJob?.cancel()
}
}
}
/**