Skip to content

fix: reset VulkanUiWatchdog pong before SetFormat to prevent 7s kill - #357

Merged
winnerspiros merged 1 commit into
masterfrom
fix/vulkan-ui-watchdog-pong
May 24, 2026
Merged

fix: reset VulkanUiWatchdog pong before SetFormat to prevent 7s kill#357
winnerspiros merged 1 commit into
masterfrom
fix/vulkan-ui-watchdog-pong

Conversation

@winnerspiros

@winnerspiros winnerspiros commented May 24, 2026

Copy link
Copy Markdown
Owner

Root cause

PR #356 fixed the native watchdog (10s) via NativeWatchdog.Heartbeat(), but missed the VulkanUiWatchdog (7s) which fires 3 seconds earlier and is the actual killer.

SetFormat blocks the UI thread for the full SurfaceDestroyed→SurfaceCreated→SurfaceChanged cycle. The Handler pong cannot run during this window. On this device (ANGLE-GC + Veldrid-AsyncPr threads adding GPU/JIT overhead), the block exceeds 7 seconds → killProcess() fires before the game ever renders.

Confirmed from build 2026.523.248.0 logs:

  • last_tick_s=0: Update thread never ran (killed before first frame)
  • ANGLE-GC thread present: extra Vulkan overhead
  • Veldrid-AsyncPr thread present: async presenter stalls
  • SDLActivity state=D: uninterruptible I/O sleep during SetFormat

Fix

  • Promote lastPongMonotonicMs from local lambda capture → vulkanWatchdogLastPongMs activity field
  • Volatile.Write to reset it alongside NativeWatchdog.Heartbeat() at both SetFormat call sites (reactive guard + proactive DecorView.Post lambda)

Files

  • osu.Android/OsuGameActivity.cs

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Improved app stability during graphics initialization on Android by preventing watchdog timeout interruptions during critical surface format transitions.

Review Change Stack

Root cause (confirmed from new logs, build 2026.523.248.0):

The VulkanUiWatchdog fires at 7s (before the native watchdog at 10s).
PR #356 reset the native watchdog via NativeWatchdog.Heartbeat() but
did NOT reset lastPongMonotonicMs — the timestamp checked by the
VulkanUiWatchdog. SetFormat blocks the UI thread for the entire
SurfaceDestroyed→SurfaceCreated→SurfaceChanged cycle. During this
window the Handler pong cannot run. With ANGLE-GC and Veldrid-AsyncPr
threads active (extra GPU/JIT overhead on affected Adreno devices),
the block exceeds 7s, the VulkanUiWatchdog fires, and killProcess()
kills the app before the game ever renders a frame.

Fix:
- Promote lastPongMonotonicMs from a local lambda capture to an
  activity field (vulkanWatchdogLastPongMs).
- Reset it via Volatile.Write alongside NativeWatchdog.Heartbeat()
  at every SetFormat call site (reactive guard + proactive lambda).

This extends the effective watchdog window from 7s to 7s + (time
since reset), which is always sufficient for SetFormat to complete
and the draw thread to resume normally.
Copilot AI review requested due to automatic review settings May 24, 2026 06:31
@coderabbitai

coderabbitai Bot commented May 24, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ad590fad-478a-4886-85fe-7672697f7a57

📥 Commits

Reviewing files that changed from the base of the PR and between 4fe73b4 and 55a452e.

📒 Files selected for processing (1)
  • osu.Android/OsuGameActivity.cs

📝 Walkthrough

Walkthrough

OsuGameActivity adds explicit watchdog coordination to prevent timeouts during surface format changes. A new shared timestamp field (vulkanWatchdogLastPongMs) is introduced and used by the Vulkan UI-thread watchdog loop to track the last pong. Before the blocking RGB565→RGBA8888 SetFormat call, both the native and Vulkan watchdogs are reset via this field and heartbeat updates, preventing spurious kills during teardown/recreation.

Changes

Vulkan Watchdog Coordination During Surface Format Changes

Layer / File(s) Summary
Watchdog state infrastructure
osu.Android/OsuGameActivity.cs
New vulkanWatchdogLastPongMs field is initialized from Environment.TickCount64 and used by startVulkanUiWatchdog to read the last-pong timestamp instead of a locally-scoped value, enabling external coordination.
Surface format change watchdog prevention
osu.Android/OsuGameActivity.cs
Before the blocking SurfaceHolder.SetFormat(Rgba8888) call in SurfaceChanged, both the native watchdog heartbeat and vulkanWatchdogLastPongMs are reset with Volatile writes to prevent the watchdog from firing during the known UI-thread blockage.

Possibly Related PRs

  • winnerspiros/osu#356: Both PRs modify osu.Android/OsuGameActivity.cs around SurfaceChanged's RGB565→RGBA8888 SurfaceHolder.SetFormat call, reordering/resetting watchdog signaling (surfaceEvent and native/Vulkan watchdog timing) to prevent watchdog shutdown/deadlock during the blocking teardown.

Estimated Code Review Effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A watchdog waits, but surface formats block,
So the Android warrens reset the clock—
Before SetFormat holds the UI thread tight,
The pong timestamp bounces fresh and bright,
No spurious kills, just cordial delight! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% 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 title 'fix: reset VulkanUiWatchdog pong before SetFormat to prevent 7s kill' directly and specifically describes the main change: resetting the Vulkan UI watchdog timestamp before SetFormat to prevent a 7-second timeout kill. It is clear, concise, and accurately summarizes the core fix.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/vulkan-ui-watchdog-pong

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.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@winnerspiros
winnerspiros merged commit 890c8f2 into master May 24, 2026
16 of 25 checks passed
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.

2 participants