fix: Make EDT coroutine modality state explicit everywhere and fix deadlocks

This commit is contained in:
FalsePattern 2025-03-27 22:02:33 +01:00
parent 6c14ad7113
commit 1f79f484e5
Signed by: falsepattern
GPG key ID: E930CDEC50C50E23
8 changed files with 15 additions and 11 deletions

View file

@ -34,6 +34,7 @@ Changelog structure reference:
- Project - Project
- File path browse buttons in zig run configurations didn't work - File path browse buttons in zig run configurations didn't work
- Occasional GUI deadlocks
- Zig - Zig
- IPC wrapper wasn't passing exit code - IPC wrapper wasn't passing exit code

View file

@ -93,7 +93,7 @@ abstract class ZigDebugRunnerBase<ProfileState : ZigProfileState<*>> : ZigProgra
} }
} }
} }
return@reportProgress runInterruptibleEDT { return@reportProgress runInterruptibleEDT(ModalityState.any()) {
val debuggerManager = XDebuggerManager.getInstance(environment.project) val debuggerManager = XDebuggerManager.getInstance(environment.project)
debuggerManager.startSession(environment, object: XDebugProcessStarter() { debuggerManager.startSession(environment, object: XDebugProcessStarter() {
override fun start(session: XDebugSession): XDebugProcess { override fun start(session: XDebugSession): XDebugProcess {

View file

@ -31,6 +31,7 @@ import com.falsepattern.zigbrains.shared.coroutine.launchWithEDT
import com.falsepattern.zigbrains.shared.coroutine.runModalOrBlocking import com.falsepattern.zigbrains.shared.coroutine.runModalOrBlocking
import com.falsepattern.zigbrains.shared.zigCoroutineScope import com.falsepattern.zigbrains.shared.zigCoroutineScope
import com.intellij.ide.plugins.PluginManager import com.intellij.ide.plugins.PluginManager
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.extensions.PluginId import com.intellij.openapi.extensions.PluginId
import com.intellij.openapi.observable.util.whenItemSelected import com.intellij.openapi.observable.util.whenItemSelected
import com.intellij.openapi.ui.ComboBox import com.intellij.openapi.ui.ComboBox
@ -88,7 +89,7 @@ class ZigDebuggerToolchainConfigurableUi : ZigDebuggerUiComponent {
row(ZigDebugBundle.message("settings.debugger.toolchain.debugger.label")) { row(ZigDebugBundle.message("settings.debugger.toolchain.debugger.label")) {
comment = cell(debuggerKindComboBox) comment = cell(debuggerKindComboBox)
.comment("", DEFAULT_COMMENT_WIDTH) { .comment("", DEFAULT_COMMENT_WIDTH) {
zigCoroutineScope.launchWithEDT { zigCoroutineScope.launchWithEDT(ModalityState.any()) {
withModalProgress(ModalTaskOwner.component(debuggerKindComboBox), "Downloading debugger", TaskCancellation.cancellable()) { withModalProgress(ModalTaskOwner.component(debuggerKindComboBox), "Downloading debugger", TaskCancellation.cancellable()) {
downloadDebugger() downloadDebugger()
} }
@ -96,7 +97,7 @@ class ZigDebuggerToolchainConfigurableUi : ZigDebuggerUiComponent {
} }
.applyToComponent { .applyToComponent {
whenItemSelected(null) { whenItemSelected(null) {
zigCoroutineScope.launchWithEDT { zigCoroutineScope.launchWithEDT(ModalityState.any()) {
this@ZigDebuggerToolchainConfigurableUi.update() this@ZigDebuggerToolchainConfigurableUi.update()
} }
} }
@ -111,7 +112,7 @@ class ZigDebuggerToolchainConfigurableUi : ZigDebuggerUiComponent {
cell(useClion) cell(useClion)
} }
} }
zigCoroutineScope.launchWithEDT { zigCoroutineScope.launchWithEDT(ModalityState.any()) {
update() update()
} }
} }

View file

@ -29,6 +29,7 @@ import com.intellij.ide.util.projectWizard.ModuleBuilder
import com.intellij.ide.util.projectWizard.ModuleWizardStep import com.intellij.ide.util.projectWizard.ModuleWizardStep
import com.intellij.ide.util.projectWizard.WizardContext import com.intellij.ide.util.projectWizard.WizardContext
import com.intellij.openapi.Disposable import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.module.ModuleType import com.intellij.openapi.module.ModuleType
import com.intellij.openapi.roots.ModifiableRootModel import com.intellij.openapi.roots.ModifiableRootModel
import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.Disposer
@ -58,7 +59,7 @@ class ZigModuleBuilder: ModuleBuilder() {
val root = contentEntry.file ?: return val root = contentEntry.file ?: return
val config = configurationData ?: return val config = configurationData ?: return
config.generateProject(this, rootModel.project, root, forceGitignore) config.generateProject(this, rootModel.project, root, forceGitignore)
withEDTContext { withEDTContext(ModalityState.defaultModalityState()) {
root.refresh(false, true) root.refresh(false, true)
} }
} }

View file

@ -95,7 +95,7 @@ class ZigProjectSettingsPanel(private val holder: ZigProjectConfigurationProvide
} }
private fun dispatchAutodetect(force: Boolean) { private fun dispatchAutodetect(force: Boolean) {
project.zigCoroutineScope.launchWithEDT { project.zigCoroutineScope.launchWithEDT(ModalityState.any()) {
withModalProgress(ModalTaskOwner.component(pathToToolchain), "Detecting Zig...", TaskCancellation.cancellable()) { withModalProgress(ModalTaskOwner.component(pathToToolchain), "Detecting Zig...", TaskCancellation.cancellable()) {
autodetect(force) autodetect(force)
} }

View file

@ -27,6 +27,7 @@ import com.falsepattern.zigbrains.project.steps.discovery.ZigStepDiscoveryListen
import com.falsepattern.zigbrains.shared.coroutine.withEDTContext import com.falsepattern.zigbrains.shared.coroutine.withEDTContext
import com.falsepattern.zigbrains.shared.zigCoroutineScope import com.falsepattern.zigbrains.shared.zigCoroutineScope
import com.intellij.openapi.Disposable import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ModalityState
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.openapi.diagnostic.Logger import com.intellij.openapi.diagnostic.Logger
@ -124,7 +125,7 @@ class ZigStepDiscoveryService(private val project: Project) {
} }
private suspend fun dispatchReload() { private suspend fun dispatchReload() {
withEDTContext { withEDTContext(ModalityState.defaultModalityState()) {
FileDocumentManager.getInstance().saveAllDocuments() FileDocumentManager.getInstance().saveAllDocuments()
} }
doReload() doReload()

View file

@ -39,7 +39,7 @@ inline fun <T> runModalOrBlocking(taskOwnerFactory: () -> ModalTaskOwner, titleF
} }
} }
suspend inline fun <T> withEDTContext(state: ModalityState = ModalityState.defaultModalityState(), noinline block: suspend CoroutineScope.() -> T): T { suspend inline fun <T> withEDTContext(state: ModalityState, noinline block: suspend CoroutineScope.() -> T): T {
return withContext(Dispatchers.EDT + state.asContextElement(), block = block) return withContext(Dispatchers.EDT + state.asContextElement(), block = block)
} }
@ -49,10 +49,10 @@ suspend inline fun <T> withCurrentEDTModalityContext(noinline block: suspend Cor
} }
} }
suspend inline fun <T> runInterruptibleEDT(state: ModalityState = ModalityState.defaultModalityState(), noinline targetAction: () -> T): T { suspend inline fun <T> runInterruptibleEDT(state: ModalityState, noinline targetAction: () -> T): T {
return runInterruptible(Dispatchers.EDT + state.asContextElement(), block = targetAction) return runInterruptible(Dispatchers.EDT + state.asContextElement(), block = targetAction)
} }
fun CoroutineScope.launchWithEDT(state: ModalityState = ModalityState.defaultModalityState(), block: suspend CoroutineScope.() -> Unit): Job { fun CoroutineScope.launchWithEDT(state: ModalityState, block: suspend CoroutineScope.() -> Unit): Job {
return launch(Dispatchers.EDT + state.asContextElement(), block = block) return launch(Dispatchers.EDT + state.asContextElement(), block = block)
} }

View file

@ -279,7 +279,7 @@ class ZLSSettingsPanel(private val project: Project) : ZigProjectConfigurationPr
} }
private fun dispatchAutodetect(force: Boolean) { private fun dispatchAutodetect(force: Boolean) {
project.zigCoroutineScope.launchWithEDT { project.zigCoroutineScope.launchWithEDT(ModalityState.any()) {
withModalProgress(ModalTaskOwner.component(zlsPath), "Detecting ZLS...", TaskCancellation.cancellable()) { withModalProgress(ModalTaskOwner.component(zlsPath), "Detecting ZLS...", TaskCancellation.cancellable()) {
autodetect(force) autodetect(force)
} }