From 63a0660cc3b520203328beb94cea68d5aa2cf859 Mon Sep 17 00:00:00 2001 From: Hung Nguyen Date: Thu, 12 Jan 2023 12:48:47 +0000 Subject: [PATCH] IC: Close caches before falling back to non-incremental compile Previously, we didn't close caches if incremental compilation failed. The assumption was that we would fall back to non-incremental compilation, where it shouldn't matter whether caches were closed or not as non-incremental compilation should be able to recover from a corrupted state of the caches. However, this choice might have caused issues such as KT-55709 where non-incremental compilation fails after fallback. In this commit, we will now always close the caches before falling back, just to be safe. TODO: 1. We'll need to verify whether not closing the caches was the actual cause of KT-55709, and that this commit fixes it. 2. Even if this commit fixes the issue, we'll need to see why non-incremental compilation fails to recover from unclosed caches (it would remain unsafe if that was not addressed). ^KT-55709 In progress (see TODO #1 above) --- .../incremental/IncrementalCompilerRunner.kt | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt index f8967e7da21..69e83c97238 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt @@ -154,6 +154,19 @@ abstract class IncrementalCompilerRunner< } changedFiles as ChangedFiles.Known? + // Because `caches` is a Closeable resource, it is important to close them in the event of an exception or before any return + // statements. + // Note: Historically, closing caches used to throw an exception sometimes, so currently we want to collect those exceptions. In the + // future, if closing caches is safe, and we are no longer interested in those exceptions, we can simplify this code by using + // Kotlin's `Closable.use` function (see `compileNonIncrementally`). + fun closeCaches(caches: CacheManager, activeException: Throwable) { + try { + caches.close() + } catch (e: Throwable) { + activeException.addSuppressed(e) + } + } + val caches = createCacheManager(args, projectDir) val exitCode: ExitCode try { @@ -161,7 +174,7 @@ abstract class IncrementalCompilerRunner< val knownChangedFiles: ChangedFiles.Known = try { getChangedFiles(changedFiles, allSourceFiles, caches) } catch (e: Throwable) { - // Don't need to close caches in cases where we return `ICResult.Failed` because we will compile non-incrementally anyway + closeCaches(caches, e) return ICResult.Failed(IC_FAILED_TO_GET_CHANGED_FILES, e) } @@ -173,6 +186,7 @@ abstract class IncrementalCompilerRunner< calculateSourcesToCompile(caches, knownChangedFiles, args, messageCollector, classpathAbiSnapshot ?: emptyMap()) } } catch (e: Throwable) { + closeCaches(caches, e) return ICResult.Failed(IC_FAILED_TO_COMPUTE_FILES_TO_RECOMPILE, e) } @@ -196,16 +210,11 @@ abstract class IncrementalCompilerRunner< exitCode = try { compileImpl(compilationMode as CompilationMode.Incremental, allSourceFiles, args, caches, abiSnapshotData, messageCollector) } catch (e: Throwable) { + closeCaches(caches, e) return ICResult.Failed(IC_FAILED_TO_COMPILE_INCREMENTALLY, e) } } catch (e: Throwable) { - // Because `caches` is a Closeable resource, it is good practice to close them in the event of an exception (in addition to - // closing them after a normal use). - try { - caches.close() - } catch (e2: Throwable) { - e.addSuppressed(e2) - } + closeCaches(caches, e) throw e } try {