Files
openide/platform/execution-impl/src/com/intellij/execution/impl/ProjectRunConfigurationInitializer.kt
Nikolay Chashnikov 394d8ad5cf [platform] initialize RunManager under read action to fix deadlock (IDEA-303213)
It may happen that RunManagerImpl::loadState invokes Read Action (e.g. inside BuildArtifactsBeforeRunTaskBase.readExternal), so if we don't invoke the whole initialization under Read Action, we may get a deadlock if some other thread accesses RunManager (and triggers its initialization) under Write Action, or accesses it under Read Action while other Write Action is pending.

GitOrigin-RevId: 8009acb892fbb3b1f24bd1b29db51d84d894db28
2022-10-07 17:54:42 +00:00

36 lines
1.7 KiB
Kotlin

// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.execution.impl
import com.intellij.diagnostic.runActivity
import com.intellij.execution.RunManager
import com.intellij.execution.RunManager.Companion.IS_RUN_MANAGER_INITIALIZED
import com.intellij.openapi.application.readAction
import com.intellij.openapi.components.ComponentManagerEx
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.impl.ProjectServiceContainerInitializedListener
import kotlinx.coroutines.async
private class ProjectRunConfigurationInitializer : ProjectServiceContainerInitializedListener {
override suspend fun execute(project: Project) {
project.coroutineScope.async {
if (IS_RUN_MANAGER_INITIALIZED.get(project) == true) {
return@async
}
// wait for module manager - may be required for module level run configurations
// it allows us to avoid thread blocking
// (RunManager itself cannot yet do the same, as platform doesn't provide non-blocking load state)
(project as ComponentManagerEx).getServiceAsync(ModuleManager::class.java).join()
runActivity("RunManager initialization") {
// we must not fire beginUpdate here, because message bus will fire queued parent message bus messages (and, so, SOE may occur because all other projectOpened will be processed before us)
// simply, you should not listen changes until project opened
readAction {
RunManager.getInstance(project)
}
IS_RUN_MANAGER_INITIALIZED.set(project, true)
}
}
}
}