Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RetroAchievements: Delay calling LoadApprovedList #12922

Merged

Conversation

JosJuice
Copy link
Member

@JosJuice JosJuice commented Jul 8, 2024

0c14b0c made Dolphin load a file from the Sys folder the first time AchievementManager::GetInstance() is called. Because Android calls AchievementManager::GetInstance() from setBackgroundExecutionAllowedNative, this had two negative consequences on Android:

  1. The first time setBackgroundExecutionAllowedNative gets called is often before directory initialization is done. Getting the path of the Sys folder before directory initialization is done causes a crash.
  2. setBackgroundExecutionAllowedNative is called from the GUI thread, and we don't want file I/O on the GUI thread for performance reasons.

This change makes us load the data from the Sys folder the first time the data is needed instead. This also saves us from having to load the data at all when hardcore mode is inactive.

Copy link
Contributor

@Dentomologist Dentomologist left a comment

Choose a reason for hiding this comment

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

Untested, and I don't know anything about the interaction with Android here, but this looks reasonable.

[Thinking out loud] Before, m_ini_root was thread safe both because of the explicit lock_guard in LoadApprovedList and because it was only loaded in the AchievementManager constructor, which was only called by the static local declared in GetInstance which in turn is guaranteed (by virtue of the rules surrounding initialization of static local variables) to be thread safe.

Now thread safety is managed by the fact that the only user of m_ini_root is FilterApprovedPatches, which is only called by LoadPatches in PatchEngine.cpp and uses AchievementManager's lock. This works, but I think it would make sense to just use the lock directly in FilterApprovedPatches since it's necessary anyway and would prevent problems if we hypothetically called the function from somewhere else and forgot to grab the lock.

JosJuice added 2 commits July 9, 2024 09:55
0c14b0c made Dolphin load a file from
the Sys folder the first time AchievementManager::GetInstance() is
called. Because Android calls AchievementManager::GetInstance() from
setBackgroundExecutionAllowedNative, this had two negative consequences
on Android:

1. The first time setBackgroundExecutionAllowedNative gets called is
   often before directory initialization is done. Getting the path of
   the Sys folder before directory initialization is done causes a crash.
2. setBackgroundExecutionAllowedNative is called from the GUI thread,
   and we don't want file I/O on the GUI thread for performance reasons.

This change makes us load the data from the Sys folder the first time
the data is needed instead. This also saves us from having to load the
data at all when hardcore mode is inactive.
There being no active patches is by far the most common case, so let's
optimize for this case.
@JosJuice JosJuice force-pushed the android-approved-list-crash branch from 1f2f76c to e6b9091 Compare July 9, 2024 08:07
@JosJuice
Copy link
Member Author

JosJuice commented Jul 9, 2024

The locking we had before didn't actually add any thread safety. LoadApprovedList was guarding m_ini_root using m_lock, but FilterApprovedPatches wasn't using m_lock at all, so the use of m_lock in LoadApprovedList was pointless. But regardless, I've made FilterApprovedPatches use m_lock like you suggested so that nothing goes wrong if we call FilterApprovedPatches from multiple threads in the future.

Copy link
Contributor

@AdmiralCurtiss AdmiralCurtiss left a comment

Choose a reason for hiding this comment

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

This seems fine and apparently fixes a crash that I can't verify (the Android code flow eludes me), so I guess we should merge it.

@AdmiralCurtiss AdmiralCurtiss merged commit bb03fc0 into dolphin-emu:master Jul 9, 2024
11 checks passed
@JosJuice JosJuice deleted the android-approved-list-crash branch July 9, 2024 19:23
@JosJuice
Copy link
Member Author

The locking we had before didn't actually add any thread safety. LoadApprovedList was guarding m_ini_root using m_lock, but FilterApprovedPatches wasn't using m_lock at all, so the use of m_lock in LoadApprovedList was pointless.

I found out now that the caller of FilterApprovedPatches was locking. That's very strange design, but anyway it seems reasonable to lock inside FilterApprovedPatches.

SternXD pushed a commit to SternXD/dolphin-uwp that referenced this pull request Feb 7, 2025
…ist-crash

RetroAchievements: Delay calling LoadApprovedList
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants