diff --git a/platform/vcs-impl/shared/src/com/intellij/platform/vcs/impl/shared/SingleTaskRunner.kt b/platform/vcs-impl/shared/src/com/intellij/platform/vcs/impl/shared/SingleTaskRunner.kt index b1da19fae3b1..eadf17b86af2 100644 --- a/platform/vcs-impl/shared/src/com/intellij/platform/vcs/impl/shared/SingleTaskRunner.kt +++ b/platform/vcs-impl/shared/src/com/intellij/platform/vcs/impl/shared/SingleTaskRunner.kt @@ -2,6 +2,7 @@ package com.intellij.platform.vcs.impl.shared import com.intellij.openapi.diagnostic.debug +import com.intellij.openapi.diagnostic.getOrHandleException import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.progress.checkCanceled import kotlinx.coroutines.* @@ -37,7 +38,9 @@ class SingleTaskRunner( busy.value = true requested.value = false checkCanceled() - task() + runCatching { + task() + }.getOrHandleException { LOG.error("Task failed", it) } busy.value = false } } diff --git a/platform/vcs-impl/testSrc/com/intellij/vcsUtil/SingleTaskRunnerTest.kt b/platform/vcs-impl/testSrc/com/intellij/vcsUtil/SingleTaskRunnerTest.kt index 12a07f9ca49b..d8ae74d222b7 100644 --- a/platform/vcs-impl/testSrc/com/intellij/vcsUtil/SingleTaskRunnerTest.kt +++ b/platform/vcs-impl/testSrc/com/intellij/vcsUtil/SingleTaskRunnerTest.kt @@ -3,6 +3,7 @@ package com.intellij.vcsUtil import com.intellij.platform.util.coroutines.childScope import com.intellij.platform.vcs.impl.shared.SingleTaskRunner +import com.intellij.testFramework.LoggedErrorProcessor import com.intellij.testFramework.common.timeoutRunBlocking import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.TimeoutCancellationException @@ -84,6 +85,31 @@ internal class SingleTaskRunnerTest { } } + @Test + fun `test thrown exception doesn't prevent further execution`() = + LoggedErrorProcessor.executeWith(allowLoggedError()) { + timeoutRunBlocking { + var counter = 0 + withRunner({ + counter++ + error("Test exception") + }) { + start() + request() + awaitNotBusy() + assertEquals(1, counter) + request() + awaitNotBusy() + assertEquals(2, counter) + } + } + } + + private fun allowLoggedError() = object : LoggedErrorProcessor() { + override fun processError(category: String, message: String, details: Array, t: Throwable?): Set = + if (message.contains("Task failed")) Action.NONE else Action.ALL + } + private inline fun CoroutineScope.withRunner( noinline task: suspend () -> Unit, delay: Duration = Duration.Companion.ZERO,