Fix possible double score submission when auto-retrying via perfect mod #26333
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Closes #26035.
submitOnFailOrQuit()
, as the name suggests, can be called both when the player has failed, or when the player screen is being exited from. Notably, when perfect mod with auto-retry is active, the two happen almost simultaneously.This double call exposes a data race in
submitScore()
concerning the handling ofscoreSubmissionSource
. The race could be experimentally confirmed by applying the following patch:which would result in the following log output:
The intention of the submission logic was to only ever create one
scoreSubmissionSource
, and then reuse this one if a redundant submission request was made. However, because of the temporal proximity of fail and quit in this particular case, combined with the fact that the calls tosubmitScore()
are taking place on TPL threads, means that there is a read-write data race onscoreSubmissionSource
, wherein the source can be actually created twice.This leads to two concurrent score submission requests, which, upon completion, attempt to transition only the second
scoreSubmissionSource
to a final state (this is because the API success/failure request callbacks capturethis
, i.e. the entireSubmittingPlayer
instance, rather than thescoreSubmissionSource
reference specifically).To fix, ensure correct synchronisation on the read-write critical section, which should prevent the
scoreSubmissionSource
from being created multiple times.