From eba00307529010db68c854e6c0fb4fe26c72576a Mon Sep 17 00:00:00 2001 From: Yuriy Artamonov Date: Sat, 15 Aug 2026 18:04:09 +0200 Subject: [PATCH] [platform] IJPL-246403 Provide cancellable alternative to EnvironmentUtil in core-api (cherry picked from commit ad21c971b6c15eefe0e782f97e5cd7587cd6166b) IJ-CR-218917 GitOrigin-RevId: 1392b105c9a38dcfe44331b537619b9861ebbb1e --- .../intellij/openapi/progress/util/utils.kt | 3 +- .../platform/ide/bootstrap/startup.kt | 33 +++++++------------ 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/platform/core-api/src/com/intellij/openapi/progress/util/utils.kt b/platform/core-api/src/com/intellij/openapi/progress/util/utils.kt index cdd54b4ee2c3..42330046c123 100644 --- a/platform/core-api/src/com/intellij/openapi/progress/util/utils.kt +++ b/platform/core-api/src/com/intellij/openapi/progress/util/utils.kt @@ -25,7 +25,8 @@ private val LOG: Logger = Logger.getInstance("#com.intellij.openapi.progress.uti fun Future.awaitWithCheckCanceled(): T { @Suppress("UsagesOfObsoleteApi") - val indicator = ProgressManager.getInstance().getProgressIndicator() + // Can be called before Application has started, services may be unavailable + val indicator = ProgressManager.getInstanceOrNull()?.getProgressIndicator() return awaitWithCheckCanceled(indicator) } diff --git a/platform/platform-impl/bootstrap/src/com/intellij/platform/ide/bootstrap/startup.kt b/platform/platform-impl/bootstrap/src/com/intellij/platform/ide/bootstrap/startup.kt index 472dd96b5440..8b187436ed9f 100644 --- a/platform/platform-impl/bootstrap/src/com/intellij/platform/ide/bootstrap/startup.kt +++ b/platform/platform-impl/bootstrap/src/com/intellij/platform/ide/bootstrap/startup.kt @@ -1,6 +1,7 @@ // Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. @file:JvmName("StartupUtil") @file:OptIn(LowLevelLocalMachineAccess::class) + package com.intellij.platform.ide.bootstrap import com.intellij.BundleBase @@ -30,7 +31,8 @@ import com.intellij.openapi.application.impl.ApplicationInfoImpl import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.diagnostic.getOrLogException import com.intellij.openapi.diagnostic.logger -import com.intellij.openapi.progress.util.checkCancelledEvenWithPCEDisabled +import com.intellij.openapi.progress.ProgressManager +import com.intellij.openapi.progress.util.awaitWithCheckCanceled import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.ShutDownTracker import com.intellij.platform.diagnostic.telemetry.impl.span @@ -41,7 +43,6 @@ import com.intellij.ui.mac.initMacApplication import com.intellij.ui.mac.screenmenu.Menu import com.intellij.ui.scale.JBUIScale import com.intellij.ui.svg.SvgCacheManager -import com.intellij.util.ConcurrencyUtil import com.intellij.util.EnvironmentUtil import com.intellij.util.PlatformUtils import com.intellij.util.ShellEnvironmentReader @@ -59,14 +60,13 @@ import kotlinx.coroutines.Deferred import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.Job -import kotlinx.coroutines.TimeoutCancellationException import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.future.asCompletableFuture import kotlinx.coroutines.job import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext -import kotlinx.coroutines.withTimeout import org.jetbrains.annotations.ApiStatus import java.awt.Toolkit import java.lang.invoke.MethodHandles @@ -81,13 +81,13 @@ import java.time.format.DateTimeFormatter import java.util.Locale import java.util.Random import java.util.concurrent.ForkJoinPool +import java.util.concurrent.Future import java.util.concurrent.atomic.AtomicReference import java.util.function.BiConsumer import java.util.function.Supplier import java.util.logging.ConsoleHandler import java.util.logging.Level import kotlin.system.exitProcess -import kotlin.time.Duration.Companion.milliseconds internal const val IDE_STARTED: String = "------------------------------------------------------ IDE STARTED ------------------------------------------------------" private const val IDE_SHUTDOWN = "------------------------------------------------------ IDE SHUTDOWN ------------------------------------------------------" @@ -537,7 +537,8 @@ private fun checkDirectory(dir: Path, kind: Int, property: String): Boolean { try { Files.deleteIfExists(tempFile) } - catch (_: Exception) { } + catch (_: Exception) { + } } return true @@ -705,9 +706,7 @@ private fun loadEnvironment(parentJob: Job, log: Logger): Boolean { override fun get(): Map { if (env == null) { - env = @Suppress("RAW_RUN_BLOCKING") runBlocking { - awaitWithCheckCanceled(envFuture) - } + env = awaitWithIndicatorIfPossible(envFuture.asCompletableFuture()) } return env!! } @@ -730,18 +729,10 @@ private fun loadEnvironment(parentJob: Job, log: Logger): Boolean { } } -private suspend fun awaitWithCheckCanceled(deferred: CompletableDeferred): T { - while (true) { - if (!deferred.isCompleted) { - checkCancelledEvenWithPCEDisabled(indicator = null) - } - try { - return withTimeout(ConcurrencyUtil.DEFAULT_TIMEOUT_MS.milliseconds) { - deferred.await() - } - } - catch (_: TimeoutCancellationException) { } - } +private fun awaitWithIndicatorIfPossible(future: Future): T? { + // Can be called before Application has started, services may be unavailable + val indicator = ProgressManager.getInstanceOrNull()?.getProgressIndicator() + return future.awaitWithCheckCanceled(indicator) } interface AppStarter {