mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-04 17:20:55 +07:00
PY-76036 PY-75988 PY-75990 PY-76065: Fix various threading issues after the new platform threading policy
All "implicit" locks are removed from the platform, so we need to call read/write action explicitly (which is a right thing to do in any case). GitOrigin-RevId: 290788bc78e39ca42f7d0f14ae4ccd16dd315ce7
This commit is contained in:
committed by
intellij-monorepo-bot
parent
888e3be3de
commit
0438f8093b
@@ -46,8 +46,10 @@ import java.util.Map;
|
|||||||
* Needs not to be instantiated and only holds static methods.
|
* Needs not to be instantiated and only holds static methods.
|
||||||
*
|
*
|
||||||
* @see PythonSdkUtil for Pyhton SDK utilities with no run-time dependencies
|
* @see PythonSdkUtil for Pyhton SDK utilities with no run-time dependencies
|
||||||
|
*
|
||||||
|
* @deprecated please use Kotlin coroutines to run processes in background
|
||||||
*/
|
*/
|
||||||
//TODO: rename to PySdkExecuteUtil or PySdkRuntimeUtil
|
@Deprecated
|
||||||
public final class PySdkUtil {
|
public final class PySdkUtil {
|
||||||
private static final Logger LOG = Logger.getInstance(PySdkUtil.class);
|
private static final Logger LOG = Logger.getInstance(PySdkUtil.class);
|
||||||
|
|
||||||
|
|||||||
@@ -334,6 +334,7 @@ public abstract class PythonSdkFlavor<D extends PyFlavorData> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@RequiresBackgroundThread(generateAssertion = false) //because of process output
|
||||||
public String getVersionString(@Nullable String sdkHome) {
|
public String getVersionString(@Nullable String sdkHome) {
|
||||||
if (sdkHome == null) {
|
if (sdkHome == null) {
|
||||||
return null;
|
return null;
|
||||||
@@ -394,6 +395,7 @@ public abstract class PythonSdkFlavor<D extends PyFlavorData> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
@RequiresBackgroundThread(generateAssertion = false) //because of process output
|
||||||
public LanguageLevel getLanguageLevel(@NotNull String sdkHome) {
|
public LanguageLevel getLanguageLevel(@NotNull String sdkHome) {
|
||||||
return getLanguageLevelFromVersionString(getVersionString(sdkHome));
|
return getLanguageLevelFromVersionString(getVersionString(sdkHome));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import com.intellij.openapi.application.ApplicationManager
|
|||||||
import com.intellij.openapi.application.EDT
|
import com.intellij.openapi.application.EDT
|
||||||
import com.intellij.openapi.application.ModalityState
|
import com.intellij.openapi.application.ModalityState
|
||||||
import com.intellij.openapi.application.asContextElement
|
import com.intellij.openapi.application.asContextElement
|
||||||
|
import com.intellij.openapi.application.writeIntentReadAction
|
||||||
import com.intellij.openapi.components.Service
|
import com.intellij.openapi.components.Service
|
||||||
import com.intellij.openapi.components.service
|
import com.intellij.openapi.components.service
|
||||||
import com.intellij.util.concurrency.ThreadingAssertions
|
|
||||||
import com.intellij.util.concurrency.annotations.RequiresBlockingContext
|
import com.intellij.util.concurrency.annotations.RequiresBlockingContext
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -25,6 +25,11 @@ private class MyService(val coroutineScope: CoroutineScope)
|
|||||||
@RequiresBlockingContext
|
@RequiresBlockingContext
|
||||||
internal fun <T : Any> Flow<T>.oneShotConsumer(consumer: Consumer<T>) {
|
internal fun <T : Any> Flow<T>.oneShotConsumer(consumer: Consumer<T>) {
|
||||||
ApplicationManager.getApplication().service<MyService>().coroutineScope.launch(Dispatchers.EDT + ModalityState.defaultModalityState().asContextElement()) {
|
ApplicationManager.getApplication().service<MyService>().coroutineScope.launch(Dispatchers.EDT + ModalityState.defaultModalityState().asContextElement()) {
|
||||||
consumer.accept(this@oneShotConsumer.first())
|
// Platform doesn't guarantee write intent lock on EDT
|
||||||
|
//todo fix all clients and remove global lock from here
|
||||||
|
val t = this@oneShotConsumer.first()
|
||||||
|
writeIntentReadAction {
|
||||||
|
consumer.accept(t)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,11 +17,7 @@ package com.jetbrains.python.sdk
|
|||||||
|
|
||||||
import com.intellij.execution.ExecutionException
|
import com.intellij.execution.ExecutionException
|
||||||
import com.intellij.execution.target.*
|
import com.intellij.execution.target.*
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
import com.intellij.openapi.application.*
|
||||||
import com.intellij.openapi.application.PathManager
|
|
||||||
import com.intellij.openapi.application.WriteAction
|
|
||||||
import com.intellij.openapi.application.invokeAndWaitIfNeeded
|
|
||||||
import com.intellij.openapi.application.runInEdt
|
|
||||||
import com.intellij.openapi.diagnostic.getOrLogException
|
import com.intellij.openapi.diagnostic.getOrLogException
|
||||||
import com.intellij.openapi.diagnostic.thisLogger
|
import com.intellij.openapi.diagnostic.thisLogger
|
||||||
import com.intellij.openapi.module.Module
|
import com.intellij.openapi.module.Module
|
||||||
@@ -43,7 +39,10 @@ import com.intellij.openapi.vfs.LocalFileSystem
|
|||||||
import com.intellij.openapi.vfs.StandardFileSystems
|
import com.intellij.openapi.vfs.StandardFileSystems
|
||||||
import com.intellij.openapi.vfs.VfsUtil
|
import com.intellij.openapi.vfs.VfsUtil
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import com.intellij.platform.ide.progress.ModalTaskOwner
|
||||||
|
import com.intellij.platform.ide.progress.runWithModalProgressBlocking
|
||||||
import com.intellij.util.PathUtil
|
import com.intellij.util.PathUtil
|
||||||
|
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread
|
||||||
import com.intellij.webcore.packaging.PackagesNotificationPanel
|
import com.intellij.webcore.packaging.PackagesNotificationPanel
|
||||||
import com.jetbrains.extensions.failure
|
import com.jetbrains.extensions.failure
|
||||||
import com.jetbrains.python.PyBundle
|
import com.jetbrains.python.PyBundle
|
||||||
@@ -59,12 +58,16 @@ import com.jetbrains.python.sdk.flavors.VirtualEnvSdkFlavor
|
|||||||
import com.jetbrains.python.sdk.flavors.conda.CondaEnvSdkFlavor
|
import com.jetbrains.python.sdk.flavors.conda.CondaEnvSdkFlavor
|
||||||
import com.jetbrains.python.target.PyTargetAwareAdditionalData
|
import com.jetbrains.python.target.PyTargetAwareAdditionalData
|
||||||
import com.jetbrains.python.ui.PyUiUtil
|
import com.jetbrains.python.ui.PyUiUtil
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import org.jetbrains.annotations.ApiStatus
|
import org.jetbrains.annotations.ApiStatus
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
|
import javax.swing.SwingUtilities
|
||||||
|
import kotlin.Result
|
||||||
import kotlin.io.path.div
|
import kotlin.io.path.div
|
||||||
import kotlin.io.path.pathString
|
import kotlin.io.path.pathString
|
||||||
|
|
||||||
@@ -187,13 +190,22 @@ fun createSdkByGenerateTask(
|
|||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
|
|
||||||
val suggestedName = suggestedSdkName ?: suggestAssociatedSdkName(homeFile.path, associatedProjectPath)
|
val sdkName = suggestedSdkName ?: if (SwingUtilities.isEventDispatchThread()) {
|
||||||
|
runWithModalProgressBlocking(ModalTaskOwner.guess(), "...") {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
suggestAssociatedSdkName(homeFile.path, associatedProjectPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
suggestAssociatedSdkName(homeFile.path, associatedProjectPath)
|
||||||
|
}
|
||||||
return SdkConfigurationUtil.setupSdk(
|
return SdkConfigurationUtil.setupSdk(
|
||||||
existingSdks.toTypedArray(),
|
existingSdks.toTypedArray(),
|
||||||
homeFile,
|
homeFile,
|
||||||
PythonSdkType.getInstance(),
|
PythonSdkType.getInstance(),
|
||||||
null,
|
null,
|
||||||
suggestedName)
|
sdkName)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showSdkExecutionException(sdk: Sdk?, e: ExecutionException, @NlsContexts.DialogTitle title: String) {
|
fun showSdkExecutionException(sdk: Sdk?, e: ExecutionException, @NlsContexts.DialogTitle title: String) {
|
||||||
@@ -378,6 +390,7 @@ fun getInnerVirtualEnvRoot(sdk: Sdk): VirtualFile? {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiresBackgroundThread
|
||||||
internal fun suggestAssociatedSdkName(sdkHome: String, associatedPath: String?): String? {
|
internal fun suggestAssociatedSdkName(sdkHome: String, associatedPath: String?): String? {
|
||||||
// please don't forget to update com.jetbrains.python.inspections.PyInterpreterInspection.Visitor#getSuitableSdkFix
|
// please don't forget to update com.jetbrains.python.inspections.PyInterpreterInspection.Visitor#getSuitableSdkFix
|
||||||
// after changing this method
|
// after changing this method
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import com.intellij.remote.ext.LanguageCaseCollector;
|
|||||||
import com.intellij.util.Consumer;
|
import com.intellij.util.Consumer;
|
||||||
import com.intellij.util.ExceptionUtil;
|
import com.intellij.util.ExceptionUtil;
|
||||||
import com.intellij.util.PlatformUtils;
|
import com.intellij.util.PlatformUtils;
|
||||||
|
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread;
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import com.jetbrains.python.PyBundle;
|
import com.jetbrains.python.PyBundle;
|
||||||
import com.jetbrains.python.PyNames;
|
import com.jetbrains.python.PyNames;
|
||||||
@@ -244,7 +245,7 @@ public final class PythonSdkType extends SdkType {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@RequiresBackgroundThread(generateAssertion = false) //because of process output
|
||||||
public static @Nullable String suggestBaseSdkName(@NotNull String sdkHome) {
|
public static @Nullable String suggestBaseSdkName(@NotNull String sdkHome) {
|
||||||
final PythonSdkFlavor flavor = PythonSdkFlavor.getFlavor(sdkHome);
|
final PythonSdkFlavor flavor = PythonSdkFlavor.getFlavor(sdkHome);
|
||||||
if (flavor == null) return null;
|
if (flavor == null) return null;
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ package com.jetbrains.python.sdk.add.v2
|
|||||||
|
|
||||||
import com.intellij.execution.ExecutionException
|
import com.intellij.execution.ExecutionException
|
||||||
import com.intellij.openapi.application.EDT
|
import com.intellij.openapi.application.EDT
|
||||||
|
import com.intellij.openapi.application.writeAction
|
||||||
import com.intellij.openapi.module.ModuleUtil
|
import com.intellij.openapi.module.ModuleUtil
|
||||||
import com.intellij.openapi.project.ProjectManager
|
import com.intellij.openapi.project.ProjectManager
|
||||||
import com.intellij.openapi.projectRoots.ProjectJdkTable
|
import com.intellij.openapi.projectRoots.ProjectJdkTable
|
||||||
import com.intellij.openapi.projectRoots.Sdk
|
import com.intellij.openapi.projectRoots.Sdk
|
||||||
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil
|
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil
|
||||||
import com.intellij.openapi.vfs.StandardFileSystems
|
import com.intellij.openapi.vfs.VfsUtil
|
||||||
import com.intellij.platform.ide.progress.ModalTaskOwner
|
import com.intellij.platform.ide.progress.ModalTaskOwner
|
||||||
import com.intellij.platform.ide.progress.TaskCancellation
|
import com.intellij.platform.ide.progress.TaskCancellation
|
||||||
import com.intellij.platform.ide.progress.withModalProgress
|
import com.intellij.platform.ide.progress.withModalProgress
|
||||||
@@ -53,13 +54,16 @@ suspend fun PythonMutableTargetAddInterpreterModel.setupVirtualenv(venvPath: Pat
|
|||||||
catch (e: InvalidPathException) {
|
catch (e: InvalidPathException) {
|
||||||
return Result.failure(e)
|
return Result.failure(e)
|
||||||
}
|
}
|
||||||
val venvPython = VirtualEnvReader.Instance.findPythonInPythonRoot(dir)?.toString()
|
val venvPython = VirtualEnvReader.Instance.findPythonInPythonRoot(dir)
|
||||||
if (venvPython == null) {
|
if (venvPython == null) {
|
||||||
return failure(message("commandLine.directoryCantBeAccessed", venvPathOnTarget))
|
return failure(message("commandLine.directoryCantBeAccessed", venvPathOnTarget))
|
||||||
}
|
}
|
||||||
|
|
||||||
val homeFile = try {
|
val homeFile = try {
|
||||||
StandardFileSystems.local().refreshAndFindFileByPath(venvPython)
|
// refresh needs write action
|
||||||
|
writeAction {
|
||||||
|
VfsUtil.findFile(venvPython, true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (e: ExecutionException) {
|
catch (e: ExecutionException) {
|
||||||
return Result.failure(e)
|
return Result.failure(e)
|
||||||
@@ -68,10 +72,13 @@ suspend fun PythonMutableTargetAddInterpreterModel.setupVirtualenv(venvPath: Pat
|
|||||||
return failure(message("commandLine.directoryCantBeAccessed", venvPathOnTarget))
|
return failure(message("commandLine.directoryCantBeAccessed", venvPathOnTarget))
|
||||||
}
|
}
|
||||||
|
|
||||||
val suggestedName = /*suggestedSdkName ?:*/ suggestAssociatedSdkName(homeFile.path, projectPath.toString())
|
// "suggest name" calls external process and can't be called from EDT
|
||||||
val newSdk = SdkConfigurationUtil.setupSdk(existingSdks.toTypedArray(), homeFile,
|
val newSdk = withContext(Dispatchers.IO) {
|
||||||
PythonSdkType.getInstance(),
|
val suggestedName = /*suggestedSdkName ?:*/ suggestAssociatedSdkName(homeFile.path, projectPath.toString())
|
||||||
false, null, suggestedName)!!
|
SdkConfigurationUtil.setupSdk(existingSdks.toTypedArray(), homeFile,
|
||||||
|
PythonSdkType.getInstance(),
|
||||||
|
false, null, suggestedName)!!
|
||||||
|
}
|
||||||
|
|
||||||
addSdk(newSdk)
|
addSdk(newSdk)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package com.jetbrains.python.util
|
|||||||
import com.intellij.openapi.application.EDT
|
import com.intellij.openapi.application.EDT
|
||||||
import com.intellij.openapi.application.ModalityState
|
import com.intellij.openapi.application.ModalityState
|
||||||
import com.intellij.openapi.application.asContextElement
|
import com.intellij.openapi.application.asContextElement
|
||||||
|
import com.intellij.openapi.application.writeIntentReadAction
|
||||||
import com.intellij.openapi.diagnostic.thisLogger
|
import com.intellij.openapi.diagnostic.thisLogger
|
||||||
import com.intellij.openapi.ui.Messages
|
import com.intellij.openapi.ui.Messages
|
||||||
import com.intellij.openapi.util.NlsSafe
|
import com.intellij.openapi.util.NlsSafe
|
||||||
@@ -56,7 +57,10 @@ object ShowingMessageErrorSync : ErrorSink {
|
|||||||
override suspend fun emit(value: @NlsSafe String) {
|
override suspend fun emit(value: @NlsSafe String) {
|
||||||
withContext(Dispatchers.EDT + ModalityState.any().asContextElement()) {
|
withContext(Dispatchers.EDT + ModalityState.any().asContextElement()) {
|
||||||
thisLogger().warn(value)
|
thisLogger().warn(value)
|
||||||
Messages.showErrorDialog(value, PyBundle.message("python.error"))
|
// Platform doesn't allow dialogs without lock for now, fix later
|
||||||
|
writeIntentReadAction {
|
||||||
|
Messages.showErrorDialog(value, PyBundle.message("python.error"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user