Fix end-of-dream busyloop and harden resume/settings against bad values - #666
Fix end-of-dream busyloop and harden resume/settings against bad values#666scottdraves wants to merge 1 commit into
Conversation
When a dream ended with an empty cache and streaming disallowed (0 quota,
fresh install), preflightNextDream(false) returned nullopt every frame and
the player re-preflighted at 60fps with no way to advance — a CPU/log
busyloop. The field trigger was a saved last_played_frame sitting on the
clip's last frame, so the resumed dream "finished" on arrival and dropped
straight into that non-streaming transition.
- PlaylistManager::preflightNextDream: when nothing is cached and streaming
was disallowed, stream the next dream as a last resort instead of returning
nullopt. Cached content is still preferred; this only fires when the cache
is empty.
- Player::SetPlaylistAtDream: clamp the resume frame to [0, frames-1] using
the dream's metadata frame count, replacing the bogus 24h@60fps ceiling that
let past-end values through. A far-past-end seek otherwise decodes zero
frames and wedges the decoder ("no frames available" spin); a value too
large is parsed as a double and crashes the settings read (see below).
- JSONStorage::GetOrSetValue: wrap the boost::json as_*() extraction in
try/catch so a malformed or out-of-range setting (an integer too large for
uint64 is parsed as a double) falls back to the default instead of throwing
and terminating the process.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@scottdraves - for whenever you come back to this, I had GPT 5.6 Sol review the PR w/ high effort and it suggests some minor adjustments:
|
Problem
When a dream ended with an empty cache and streaming disallowed (0 quota, fresh install),
preflightNextDream(false)returnednulloptevery frame and the player re-preflighted at ~60fps with no way to advance — a CPU/log busyloop.The field trigger was a saved
last_played_framesitting on the clip's last frame: the resumed dream decoded ~1 frame, "finished" on arrival, and dropped straight into the non-streaming natural transition, which then spun.Changes
PlaylistManager::preflightNextDream— the actual fix. When nothing is cached and streaming was disallowed, stream the next dream as a last resort instead of returningnullopt. Cached content is still preferred above this; it only fires when the cache is empty.Player::SetPlaylistAtDream— clamp the resume frame to[0, frames-1]using the dream's metadata frame count, replacing the bogus24h@60fpsceiling that let past-end values through. A far-past-end seek otherwise decodes zero frames and wedges the decoder (no frames availablespin).JSONStorage::GetOrSetValue— wrap the boost::jsonas_*()extraction intry/catchso a malformed or out-of-range setting (an integer too large foruint64is parsed as a double) falls back to the default instead of throwing and terminating the process.Verification
Tested against the live Windows client with the exact field repro and a robustness battery on
last_played_frame:last_played_frame7225(last frame, 0 quota, empty cache)-10050000(past 7226-frame end)no frames available×655)~1e18~1e23(exceeds uint64)0xC0000409Confirmed end-to-end (empty cache): resume past end →
clamping to last frame→Decoder ended with only 1 frames→Preflight : no cached dreams available; streaming next dream at position 1→ next dream streams. No spin, no crash.🤖 Generated with Claude Code