Skip to content

fix: timer thread livelock caused by mutating active timer keys - #155

Open
HopeSuffers wants to merge 1 commit into
N64Recomp:mainfrom
HopeSuffers:fix/timer-set-key-mutation
Open

HopeSuffers wants to merge 1 commit into
N64Recomp:mainfrom
HopeSuffers:fix/timer-set-key-mutation

Conversation

@HopeSuffers

Copy link
Copy Markdown

Should fix BanjoRecomp/BanjoRecomp#315.

timer_thread keeps its active timers in a std::set sorted by each timer's deadline, and it reads that deadline out of game memory every time it compares two of them:

if (a->timestamp != b->timestamp) {
return a->timestamp < b->timestamp;
}

The game writes to that same field every time it re-arms a timer, and osStopTimer only queues the removal for later. So the deadline changes while the timer is still sitting in the set, and the set ends up sorted by values that no longer match where things actually are.

Once that happens, begin() still hands you the timer, but erase() can't find it any more. It walks down the wrong branch and removes nothing. So the thread keeps pulling the same timer off the front: its deadline is in the past, so it never waits, fires it, and goes straight round again. The message queue fills up until the game is wedged. In a sample of a frozen build the timer thread has zero samples in the wait and ~1200 in the enqueue.

The fix is to stop reading the deadline out of game memory. Timers are keyed on a copy taken when they're armed, so the game can't change it behind our back.

Tested on an M4. The old code strands 432,884 timers in a 200k-operation soak, the new code strands none, and I played a debug build for 2h45m with no freeze and flat memory.

@HopeSuffers
HopeSuffers force-pushed the fix/timer-set-key-mutation branch from 713aeae to 0934637 Compare September 20, 2026 10:33
@HopeSuffers HopeSuffers changed the title Fix timer thread livelock caused by mutating active timer keys fix: timer thread livelock caused by mutating active timer keys Sep 20, 2026
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.

[MacOS 14.4] Game freezing after 10+ minutes of gameplay

1 participant