Skip to content

fix: resolve resource leaks in stream handling and VACUUM INTO - #65

Merged
zly2006 merged 1 commit into
zly2006:stonecutterfrom
huanqiugame:fix/resource-leaks
Jul 19, 2026
Merged

fix: resolve resource leaks in stream handling and VACUUM INTO#65
zly2006 merged 1 commit into
zly2006:stonecutterfrom
huanqiugame:fix/resource-leaks

Conversation

@huanqiugame

Copy link
Copy Markdown
Contributor

English

Summary

This PR fixes several resource leak bugs in the backup system that cause file descriptor exhaustion and database connection leaks on long-running servers. Closes #64

This PR uses AI.

Changes

1. Fix ZipInputStream returned closed (compress type 2)

BackupDatabaseService.kt:156

The old code ZipInputStream(...).use { ... it } returned a closed stream because Kotlin's .use {} closes the resource before returning the block result. All callers (packFiles, zipArchive) would receive a closed stream and throw IOException: Stream closed when trying to read compress-type-2 entries.

Fix: Changed .use to .also, which returns the open stream after executing the block.

2. Fix exception-unsafe stream close in packFiles and zipArchive

BackupDatabaseService.kt:601, 654

The old pattern input.copyTo(target); input.close() is not exception-safe. If copyTo() throws (disk full, broken pipe), close() never executes, leaking the underlying FileInputStream.

Fix: Replaced with input.use { s -> s.copyTo(target) }, which guarantees cleanup even on exception.

3. Fix VACUUM INTO connection leak in scheduled backup

XBackup.kt:310

The old code created a new Exposed DatabaseConnection and JDBC Statement but never closed either. This code runs inside the crontab loop (every ~10 seconds when a backup is due), so each scheduled backup leaked one connection + Statement. Over time this causes "database is locked" errors.

Fix: Added try/finally { exposedConn.close() } for the connection and .use {} for the statement.

Testing

Tested in-game: manual/automatic backup, restore, and all CLI commands work correctly. Server runs stable for over 11 days without crashes after installing this fix.


中文

概述

本PR修复了备份系统中的多个资源泄漏问题,这些问题会导致长时间运行的服务器出现文件描述符耗尽和数据库连接泄漏。关闭issue #64

此PR使用AI编写。

修改内容

1. 修复 ZipInputStream 返回已关闭流的问题(压缩类型2)

BackupDatabaseService.kt:156

旧代码 ZipInputStream(...).use { ... it } 返回了一个已关闭的流,因为 Kotlin 的 .use {} 会在返回块结果之前关闭资源。所有调用者(packFiles、zipArchive)在读取压缩类型2的条目时都会收到一个已关闭的流,并抛出 IOException: Stream closed

修复:.use 改为 .also,后者在执行块后返回打开的流。

2. 修复 packFiles 和 zipArchive 中不安全的流关闭方式

BackupDatabaseService.kt:601, 654

旧模式 input.copyTo(target); input.close() 不具备异常安全性。如果 copyTo() 抛出异常(磁盘满、管道断裂),close() 永远不会执行,导致底层 FileInputStream 泄漏。

修复: 替换为 input.use { s -> s.copyTo(target) },确保即使在异常情况下也能正确清理资源。

3. 修复定时备份中 VACUUM INTO 的连接泄漏

XBackup.kt:310

旧代码创建了新的 Exposed DatabaseConnection 和 JDBC Statement,但从未关闭它们。这段代码在定时任务循环中运行(备份就绪时每~10秒一次),因此每次定时备份都会泄漏一个连接和Statement。长时间运行后会导致 "database is locked" 错误。

修复: 使用 try/finally { exposedConn.close() } 关闭连接,使用 .use {} 关闭Statement。

测试

已在游戏内测试:手动/自动备份、恢复(restore)功能正常,其他命令行功能正常。安装后服务器可正常运行超过11天不崩溃。

- 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.
@zly2006
zly2006 merged commit 6fdea0d into zly2006:stonecutter Jul 19, 2026
2 checks passed
@zly2006

zly2006 commented Jul 19, 2026

Copy link
Copy Markdown
Owner

这些修复基本上没问题,但是是否真正解决了内存泄露,还需要你帮忙确认测试。谢谢你!

@huanqiugame

Copy link
Copy Markdown
Contributor Author

在提PR之前我已经安装在服务器上并测试过了,没有出现之前的泄漏问题😉 感谢合并!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Memory leaks and game crashes after long uptime 游戏长期运行会发生内存泄漏、游戏崩溃

2 participants