From 8a4bd9a19a3472de92f3946a79965f5d848e4d8e Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sat, 23 Nov 2024 13:14:19 +0200 Subject: [PATCH] Fix "Deflater has been closed" error --- .../koitharu/kotatsu/core/zip/ZipOutput.kt | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/zip/ZipOutput.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/zip/ZipOutput.kt index 509ff3287..98515cbbb 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/zip/ZipOutput.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/zip/ZipOutput.kt @@ -5,6 +5,7 @@ import androidx.collection.ArraySet import okhttp3.internal.closeQuietly import okio.Closeable import org.jetbrains.annotations.Blocking +import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug import org.koitharu.kotatsu.core.util.ext.withChildren import java.io.File import java.io.FileInputStream @@ -13,6 +14,8 @@ import java.util.zip.Deflater import java.util.zip.ZipEntry import java.util.zip.ZipFile import java.util.zip.ZipOutputStream +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract class ZipOutput( val file: File, @@ -21,6 +24,7 @@ class ZipOutput( private val entryNames = ArraySet() private var cachedOutput: ZipOutputStream? = null + private var append: Boolean = false @Blocking fun put(name: String, file: File): Boolean = withOutput { output -> @@ -77,7 +81,11 @@ class ZipOutput( @Synchronized override fun close() { - cachedOutput?.close() + try { + cachedOutput?.close() + } catch (e: NullPointerException) { + e.printStackTraceDebug() + } cachedOutput = null } @@ -133,9 +141,21 @@ class ZipOutput( @Synchronized private fun withOutput(block: (ZipOutputStream) -> T): T { - val output = cachedOutput ?: newOutput(append = false) - val res = block(output) - output.flush() + contract { + callsInPlace(block, InvocationKind.AT_LEAST_ONCE) + } + return try { + (cachedOutput ?: newOutput(append)).withOutputImpl(block).also { + append = true // after 1st success write + } + } catch (e: NullPointerException) { // probably NullPointerException: Deflater has been closed + newOutput(append).withOutputImpl(block) + } + } + + private fun ZipOutputStream.withOutputImpl(block: (ZipOutputStream) -> T): T { + val res = block(this) + flush() return res }