From d901e6b218842152f6ab3abce701f1f342db2848 Mon Sep 17 00:00:00 2001 From: huanqiugame Date: Sun, 19 Jul 2026 20:51:52 +0800 Subject: [PATCH] fix: resolve resource leaks in stream handling and VACUUM INTO - Fix ZipInputStream returned closed: change .use{} to .also{} in getInputStreamInternal so compress-type-2 entries return an open stream instead of a closed one that causes IOException on read. - Fix exception-unsafe close in packFiles and zipArchive: replace input.copyTo(); input.close() with input.use{} to guarantee cleanup even when copyTo throws (e.g., disk full). - Fix VACUUM INTO connection leak in scheduled backup: close the Exposed DatabaseConnection via try/finally and the JDBC Statement via .use{}, preventing connection leaks on every scheduled backup cycle. --- .../github/zly2006/xbackup/BackupDatabaseService.kt | 9 +++------ .../kotlin/com/github/zly2006/xbackup/XBackup.kt | 12 ++++++++++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/common/src/main/kotlin/com/github/zly2006/xbackup/BackupDatabaseService.kt b/common/src/main/kotlin/com/github/zly2006/xbackup/BackupDatabaseService.kt index b70bb17..7eaa69a 100644 --- a/common/src/main/kotlin/com/github/zly2006/xbackup/BackupDatabaseService.kt +++ b/common/src/main/kotlin/com/github/zly2006/xbackup/BackupDatabaseService.kt @@ -153,14 +153,13 @@ class BackupDatabaseService( 1 -> withContext(Dispatchers.IO) { GZIPInputStream(blob.inputStream()) } - 2 -> ZipInputStream(blob.inputStream()).use { + 2 -> ZipInputStream(blob.inputStream()).also { @Suppress("ControlFlowWithEmptyBody") while (it.nextEntry.let { zipEntry -> if (zipEntry == null) false else zipEntry.name != path }) { } - it } else -> error("Unknown compress type: $compress") @@ -602,8 +601,7 @@ class BackupDatabaseService( val input = requireNotNull(it.getInputStreamInternal(this)) { "Blob not found for file ${it.path}, hash: ${it.hash}" } - input.copyTo(zip) - input.close() + input.use { s -> s.copyTo(zip) } } } val md5 = MessageDigest.getInstance("MD5").digest(stream.toByteArray()) @@ -656,8 +654,7 @@ class BackupDatabaseService( val input = requireNotNull(it.getInputStream(this)) { "Blob not found for file ${it.path}, hash: ${it.hash}" } - input.copyTo(outputStream) - input.close() + input.use { s -> s.copyTo(outputStream) } } done++ activeTaskProgress = 100 * done / backup.entries.size diff --git a/src/main/kotlin/com/github/zly2006/xbackup/XBackup.kt b/src/main/kotlin/com/github/zly2006/xbackup/XBackup.kt index 4b88be9..f9c392b 100644 --- a/src/main/kotlin/com/github/zly2006/xbackup/XBackup.kt +++ b/src/main/kotlin/com/github/zly2006/xbackup/XBackup.kt @@ -307,8 +307,16 @@ object XBackup : ModInitializer { val localBackup = File("x_backup.db.back") localBackup.delete() try { - (service.database.connector().connection as? SQLiteConnection)?.createStatement() - ?.execute("VACUUM INTO '$localBackup';") + val exposedConn = service.database.connector() + try { + (exposedConn.connection as? SQLiteConnection)?.let { conn -> + conn.createStatement().use { stmt -> + stmt.execute("VACUUM INTO '$localBackup';") + } + } + } finally { + exposedConn.close() + } } catch (e: Exception) { log.error("Error backing up database", e) }