fix: catch exceptions from closing patches

This commit is contained in:
oSumAtrIX 2023-06-14 02:14:37 +02:00
parent b8151ebccb
commit d5d6f85084
No known key found for this signature in database
GPG Key ID: A9B3094ACDB604B4
2 changed files with 34 additions and 22 deletions

View File

@ -23,6 +23,7 @@ import lanchon.multidexlib2.MultiDexIO
import org.jf.dexlib2.Opcodes import org.jf.dexlib2.Opcodes
import org.jf.dexlib2.iface.DexFile import org.jf.dexlib2.iface.DexFile
import org.jf.dexlib2.writer.io.MemoryDataStore import org.jf.dexlib2.writer.io.MemoryDataStore
import java.io.Closeable
import java.io.File import java.io.File
import java.io.OutputStream import java.io.OutputStream
import java.nio.file.Files import java.nio.file.Files
@ -350,7 +351,7 @@ class Patcher(private val options: PatcherOptions) {
val executedPatches = LinkedHashMap<String, ExecutedPatch>() // first is name val executedPatches = LinkedHashMap<String, ExecutedPatch>() // first is name
try {
context.patches.forEach { patch -> context.patches.forEach { patch ->
val patchResult = executePatch(patch, executedPatches) val patchResult = executePatch(patch, executedPatches)
@ -360,12 +361,30 @@ class Patcher(private val options: PatcherOptions) {
Result.failure(patchResult.error()!!) Result.failure(patchResult.error()!!)
} }
// TODO: This prints before the patch really finishes in case it is a Closeable
// because the Closeable is closed after all patches are executed.
yield(patch.patchName to result) yield(patch.patchName to result)
if (stopOnError && patchResult.isError()) return@sequence if (stopOnError && patchResult.isError()) return@sequence
} }
} finally {
executedPatches.values.filter { it.success }.reversed().forEach { (patch, _) -> executedPatches.values
patch.close() .filter(ExecutedPatch::success)
.map(ExecutedPatch::patchInstance)
.filterIsInstance(Closeable::class.java)
.asReversed().forEach {
try {
it.close()
} catch (exception: Exception) {
val patchName = (it as Patch<Context>).javaClass.patchName
logger.error("Failed to close '$patchName': ${exception.stackTraceToString()}")
yield(patchName to Result.failure(exception))
// This is not failsafe. If a patch throws an exception while closing,
// the other patches that depend on it may fail.
if (stopOnError) return@sequence
} }
} }
} }

View File

@ -12,7 +12,7 @@ import java.io.Closeable
* If it implements [Closeable], it will be closed after all patches have been executed. * If it implements [Closeable], it will be closed after all patches have been executed.
* Closing will be done in reverse execution order. * Closing will be done in reverse execution order.
*/ */
sealed interface Patch<out T : Context> : Closeable { sealed interface Patch<out T : Context> {
/** /**
* The main function of the [Patch] which the patcher will call. * The main function of the [Patch] which the patcher will call.
* *
@ -20,13 +20,6 @@ sealed interface Patch<out T : Context> : Closeable {
* @return The result of executing the patch. * @return The result of executing the patch.
*/ */
fun execute(context: @UnsafeVariance T): PatchResult fun execute(context: @UnsafeVariance T): PatchResult
/**
* The closing function for this patch.
*
* This can be treated like popping the patch from the current patch stack.
*/
override fun close() {}
} }
/** /**