AchievementManager: Don't store pointer to rc_runtime_event_t in lambda.

Scope issue in the event callback from `rc_runtime_do_frame()`. The pointer points to a variable on the stack from inside `rc_runtime_do_frame()`, so that's a race condition between the thread calling `rc_runtime_do_frame()` and the event queue thread.
This commit is contained in:
Admiral H. Curtiss 2023-10-11 10:20:05 +02:00
parent 601767c1c8
commit 111c1ab531
No known key found for this signature in database
GPG Key ID: F051B4C4044F33FB
1 changed files with 12 additions and 11 deletions

View File

@ -1088,15 +1088,15 @@ AchievementManager::PingRichPresence(const RichPresence& rich_presence)
void AchievementManager::HandleAchievementTriggeredEvent(const rc_runtime_event_t* runtime_event)
{
auto it = m_unlock_map.find(runtime_event->id);
const auto event_id = runtime_event->id;
auto it = m_unlock_map.find(event_id);
if (it == m_unlock_map.end())
{
ERROR_LOG_FMT(ACHIEVEMENTS, "Invalid achievement triggered event with id {}.",
runtime_event->id);
ERROR_LOG_FMT(ACHIEVEMENTS, "Invalid achievement triggered event with id {}.", event_id);
return;
}
it->second.session_unlock_count++;
m_queue.EmplaceItem([this, runtime_event] { AwardAchievement(runtime_event->id); });
m_queue.EmplaceItem([this, event_id] { AwardAchievement(event_id); });
AchievementId game_data_index = it->second.game_data_index;
OSD::AddMessage(fmt::format("Unlocked: {} ({})", m_game_data.achievements[game_data_index].title,
m_game_data.achievements[game_data_index].points),
@ -1115,7 +1115,7 @@ void AchievementManager::HandleAchievementTriggeredEvent(const rc_runtime_event_
fmt::format("Congratulations! {} has completed {}", m_display_name, m_game_data.title),
OSD::Duration::VERY_LONG, OSD::Color::CYAN);
}
ActivateDeactivateAchievement(runtime_event->id, Config::Get(Config::RA_ACHIEVEMENTS_ENABLED),
ActivateDeactivateAchievement(event_id, Config::Get(Config::RA_ACHIEVEMENTS_ENABLED),
Config::Get(Config::RA_UNOFFICIAL_ENABLED),
Config::Get(Config::RA_ENCORE_ENABLED));
}
@ -1175,15 +1175,16 @@ void AchievementManager::HandleLeaderboardCanceledEvent(const rc_runtime_event_t
void AchievementManager::HandleLeaderboardTriggeredEvent(const rc_runtime_event_t* runtime_event)
{
m_queue.EmplaceItem(
[this, runtime_event] { SubmitLeaderboard(runtime_event->id, runtime_event->value); });
const auto event_id = runtime_event->id;
const auto event_value = runtime_event->value;
m_queue.EmplaceItem([this, event_id, event_value] { SubmitLeaderboard(event_id, event_value); });
for (u32 ix = 0; ix < m_game_data.num_leaderboards; ix++)
{
if (m_game_data.leaderboards[ix].id == runtime_event->id)
if (m_game_data.leaderboards[ix].id == event_id)
{
FormattedValue value{};
rc_runtime_format_lboard_value(value.data(), static_cast<int>(value.size()),
runtime_event->value, m_game_data.leaderboards[ix].format);
rc_runtime_format_lboard_value(value.data(), static_cast<int>(value.size()), event_value,
m_game_data.leaderboards[ix].format);
if (std::find(value.begin(), value.end(), '\0') == value.end())
{
OSD::AddMessage(fmt::format("Scored {} on leaderboard: {}",
@ -1200,7 +1201,7 @@ void AchievementManager::HandleLeaderboardTriggeredEvent(const rc_runtime_event_
return;
}
}
ERROR_LOG_FMT(ACHIEVEMENTS, "Invalid leaderboard triggered event with id {}.", runtime_event->id);
ERROR_LOG_FMT(ACHIEVEMENTS, "Invalid leaderboard triggered event with id {}.", event_id);
}
// Every RetroAchievements API call, with only a partial exception for fetch_image, follows