Skip to content

fix: tolerate locked log rollover on Windows#2234

Open
BFlameSwift wants to merge 2 commits into
OneDragon-Anything:mainfrom
BFlameSwift:codex/fix-log-rollover-lock
Open

fix: tolerate locked log rollover on Windows#2234
BFlameSwift wants to merge 2 commits into
OneDragon-Anything:mainfrom
BFlameSwift:codex/fix-log-rollover-lock

Conversation

@BFlameSwift
Copy link
Copy Markdown

@BFlameSwift BFlameSwift commented May 7, 2026

Summary

  • add a safe timed rotating log handler that tolerates Windows PermissionError during log rollover
  • keep logging usable when another OneDragon process temporarily holds .log/log.txt
  • avoid repeated --- Logging error --- tracebacks that can flood unattended runners and obscure the real automation state

Problem solved

On Windows, TimedRotatingFileHandler rotates the log by renaming the active file, for example:

.log/log.txt -> .log/log.txt.2026-05-06

If a previous OneDragon process is still alive, or two OneDragon processes write the same log file around midnight, Windows can reject that rename because the source file is still open by another process:

PermissionError: [WinError 32] another process is using this file

After that failure, the handler still considers the file due for rollover. That means every later log write can try the same failing rename again, producing repeated Logging error stack traces instead of normal progress logs.

In unattended launchers such as ScriptChainer, this can make the task look stuck or fail early because the child process keeps emitting logging exceptions, the useful state transitions are buried, and normal startup/enter-game diagnostics become unreliable. In the observed failure, the automation started the game but then failed around the enter-world step with 未识别到大世界, while the runner log was dominated by repeated rollover PermissionError traces.

Root cause

The default TimedRotatingFileHandler is not safe for this Windows multi-process/log-file-lock scenario. A stale process holding yesterday's log.txt can make a new run repeatedly fail rollover before normal logging can continue cleanly.

Fix

This PR wraps TimedRotatingFileHandler.doRollover() and handles PermissionError by:

  • keeping/reopening the current log stream so logging can continue
  • recomputing the next rollover time so each log record does not retry the same failed rename immediately
  • using the safe handler only for the existing .log/log.txt setup, without changing log format or call sites

This does not try to kill stale processes or solve unrelated game-window/OCR failures. It prevents a locked log file from turning into a repeated logging failure loop that destabilizes or hides the actual automation state.

Verification

  • Ran py_compile for src/one_dragon/utils/log_utils.py
  • Ran git diff --check
  • Verified locally that, after clearing stale processes, the one-dragon run can enter the game, reach the world screen, and complete the one-dragon workflow

Summary by CodeRabbit

  • Bug Fixes
    • 日志系统可靠性改进 — 当日志轮转因文件权限或访问失败时,系统能自动处理并调整下一次轮转时间以继续写入,避免因轮转失败导致日志中断或丢失。

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 7, 2026

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b2061798-a957-4a3b-a342-7dc94943c939

📥 Commits

Reviewing files that changed from the base of the PR and between 4e68f6d and 83f37e9.

📒 Files selected for processing (1)
  • src/one_dragon/utils/log_utils.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/one_dragon/utils/log_utils.py

📝 Walkthrough

Walkthrough

新增 SafeTimedRotatingFileHandler(继承 TimedRotatingFileHandler),在 doRollover 中捕获 PermissionError 并重算/推进 rolloverAt;get_logger() 改用该处理器,轮换参数保持不变。

日志轮换错误处理

Layer / File(s) Summary
数据结构与类定义
src/one_dragon/utils/log_utils.py
新增 SafeTimedRotatingFileHandler 类,继承 TimedRotatingFileHandler,重写 doRollover() 方法以捕获 PermissionError
核心错误恢复逻辑
src/one_dragon/utils/log_utils.py
doRollover() 在捕获 PermissionError 后确保 stream 已打开(若无则 _open()),使用 computeRollover() 基于当前时间循环推进并更新 rolloverAt
logger 初始化集成
src/one_dragon/utils/log_utils.py
get_logger() 将文件轮换处理器从 TimedRotatingFileHandler 更改为 SafeTimedRotatingFileHandler,保持 when='midnight'interval=1backupCountencoding 等参数不变。

代码审查工作量估计

🎯 2 (Simple) | ⏱️ ~10 分钟

可能相关的问题

诗句

🐰 我是一只代码兔,
权限阻挡我不慌,
轮换时间我来算,
日志稳妥又安详,
SafeHandler 护记录长!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'fix: tolerate locked log rollover on Windows' clearly and specifically describes the main change: handling permission errors during log file rollover on Windows.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/one_dragon/utils/log_utils.py`:
- Line 10: The override method doRollover in class defined in
src/one_dragon/utils/log_utils.py is missing a return type annotation; update
its signature from def doRollover(self) to def doRollover(self) -> None so it
complies with the repository rule that all function signatures must have type
annotations (keep the body unchanged and ensure any subclass/base-class
compatibility remains intact).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4349d4a0-5ce4-4301-bd36-08ecd67613f0

📥 Commits

Reviewing files that changed from the base of the PR and between 66ac7c1 and 4e68f6d.

📒 Files selected for processing (1)
  • src/one_dragon/utils/log_utils.py

Comment thread src/one_dragon/utils/log_utils.py Outdated
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.

1 participant