fix deadlock when service was called from EDT; more reliable Future completion (IDEA-363192)

(cherry picked from commit 8cad354fe3aca848312026b4a670bd71cfe40e62)

IJ-CR-150469

GitOrigin-RevId: d7637501a7a11d02c3d6050246d42e2563e34275
This commit is contained in:
Eugene Zhuravlev
2024-11-28 19:09:31 +01:00
committed by intellij-monorepo-bot
parent 24faeed3f3
commit 397601365f
2 changed files with 33 additions and 8 deletions

View File

@@ -1,27 +1,32 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// 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.ui.content.impl
import com.intellij.concurrency.captureThreadContext
import com.intellij.icons.AllIcons
import com.intellij.openapi.application.EDT
import com.intellij.openapi.components.serviceAsync
import com.intellij.openapi.diagnostic.thisLogger
import com.intellij.openapi.project.Project
import com.intellij.openapi.startup.StartupManager
import com.intellij.openapi.wm.ToolWindow
import com.intellij.openapi.wm.ToolWindowId
import com.intellij.openapi.wm.ToolWindowManager
import com.intellij.ui.UIBundle
import com.intellij.ui.content.ContentManager
import com.intellij.ui.content.MessageView
import com.intellij.util.ui.EDT
import kotlinx.coroutines.*
import kotlinx.coroutines.future.asCompletableFuture
internal class MessageViewImpl(project: Project, scope: CoroutineScope) : MessageView {
private val toolWindow = scope.async(Dispatchers.EDT, start = CoroutineStart.LAZY) {
project.serviceAsync<ToolWindowManager>().registerToolWindow(ToolWindowId.MESSAGES_WINDOW) {
icon = AllIcons.Toolwindows.ToolWindowMessages
stripeTitle = UIBundle.messagePointer("tool.window.name.messages")
internal class MessageViewImpl(private val project: Project, private val scope: CoroutineScope) : MessageView {
private val toolWindow: Deferred<ToolWindow> =
if (EDT.isCurrentThreadEdt()) {
CompletableDeferred(registerToolWindow(project))
}
}
else {
scope.async(Dispatchers.EDT, start = CoroutineStart.LAZY) { registerToolWindowAsync(project) }
}
private val postponedRunnables = ArrayList<Runnable>()
init {
@@ -31,7 +36,12 @@ internal class MessageViewImpl(project: Project, scope: CoroutineScope) : Messag
withContext(Dispatchers.EDT) {
for (postponedRunnable in postponedRunnables) {
postponedRunnable.run()
try {
postponedRunnable.run()
}
catch (e: Throwable) {
thisLogger().error(e) // unexpected
}
}
postponedRunnables.clear()
@@ -63,4 +73,18 @@ internal class MessageViewImpl(project: Project, scope: CoroutineScope) : Messag
override suspend fun awaitInitialized() {
toolWindow.await()
}
companion object {
private const val TW_ID = ToolWindowId.MESSAGES_WINDOW
private val TW_ICON = AllIcons.Toolwindows.ToolWindowMessages
private val TW_TITLE = UIBundle.messagePointer("tool.window.name.messages")
private suspend fun registerToolWindowAsync(project: Project): ToolWindow {
return project.serviceAsync<ToolWindowManager>().registerToolWindow(TW_ID) { icon = TW_ICON; stripeTitle = TW_TITLE }
}
private fun registerToolWindow(project: Project): ToolWindow {
return ToolWindowManager.getInstance(project).registerToolWindow(TW_ID) { icon = TW_ICON; stripeTitle = TW_TITLE }
}
}
}

View File

@@ -149,6 +149,7 @@ public final class ExecutionHandler {
}
}
catch (Throwable e) {
future.complete(null);
LOG.error(e);
listenerWrapper.buildFinished(AntBuildListener.FAILED_TO_RUN, 0);
}