Merge pull request 'fix(fs): race condition in save mirroring during config changes' (#83) from fix/mirroring into main

Reviewed-on: https://git.citron-emu.org/Citron/Emulator/pulls/83
This commit is contained in:
Collecting
2026-01-03 04:39:43 +00:00
3 changed files with 15 additions and 9 deletions

View File

@@ -954,8 +954,13 @@ void GameList::DonePopulating(const QStringList& watch_list) {
}
}
LOG_INFO(Frontend, "Game List populated. Triggering Mirror Sync...");
system.GetFileSystemController().GetSaveDataFactory().PerformStartupMirrorSync();
// Only sync if we aren't rebuilding the UI and the game isn't running.
if (main_window && !main_window->IsConfiguring() && !system.IsPoweredOn()) {
LOG_INFO(Frontend, "Game List populated. Triggering Mirror Sync...");
system.GetFileSystemController().GetSaveDataFactory().PerformStartupMirrorSync();
} else {
LOG_INFO(Frontend, "Mirroring: Startup sync skipped (Reason: UI Busy or Game is Emulating).");
}
emit PopulatingCompleted();
}

View File

@@ -4087,6 +4087,7 @@ void GMainWindow::ResetWindowSize1080() {
}
void GMainWindow::OnConfigure() {
m_is_configuring = true;
const auto old_theme = UISettings::values.theme;
const bool old_discord_presence = UISettings::values.enable_discord_presence.GetValue();
const auto old_language_index = Settings::values.language_index.GetValue();
@@ -4105,13 +4106,10 @@ void GMainWindow::OnConfigure() {
if (result != QDialog::Accepted && !UISettings::values.configuration_applied &&
!UISettings::values.reset_to_defaults) {
// Runs if the user hit Cancel or closed the window, and did not ever press the Apply button
// or `Reset to Defaults` button
// Runs if the user hit Cancel or closed the window
m_is_configuring = false;
return;
} else if (result == QDialog::Accepted) {
// Only apply new changes if user hit Okay
// This is here to avoid applying changes if the user hit Apply, made some changes, then hit
// Cancel
configure_dialog.ApplyConfiguration();
} else if (UISettings::values.reset_to_defaults) {
LOG_INFO(Frontend, "Resetting all settings to defaults");
@@ -4127,8 +4125,6 @@ void GMainWindow::OnConfigure() {
LOG_WARNING(Frontend, "Failed to remove game metadata cache files");
}
// Explicitly save the game directories, since reinitializing config does not explicitly do
// so.
QVector<UISettings::GameDir> old_game_dirs = std::move(UISettings::values.game_dirs);
QVector<u64> old_favorited_ids = std::move(UISettings::values.favorited_ids);
@@ -4197,6 +4193,8 @@ void GMainWindow::OnConfigure() {
UpdateStatusButtons();
controller_dialog->refreshConfiguration();
system->ApplySettings();
m_is_configuring = false;
}
void GMainWindow::OnConfigureTas() {

View File

@@ -105,6 +105,7 @@ class GMainWindow : public QMainWindow {
public:
void filterBarSetChecked(bool state);
void UpdateUITheme();
bool IsConfiguring() const { return m_is_configuring; }
explicit GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulkan);
~GMainWindow() override;
bool DropAction(QDropEvent* event);
@@ -197,6 +198,7 @@ private:
Service::AM::FrontendAppletParameters ApplicationAppletParameters();
Service::AM::FrontendAppletParameters LibraryAppletParameters(u64 program_id, Service::AM::AppletId applet_id);
std::unique_ptr<FileSys::ManualContentProvider> autoloader_provider;
u64 current_title_id{0};
private slots:
void OnStartGame();
void OnRestartGame();
@@ -398,6 +400,7 @@ private:
bool is_load_file_select_active{};
bool is_tas_recording_dialog_active{};
bool m_is_updating_theme = false;
bool m_is_configuring = false;
#ifdef __unix__
QSocketNotifier* sig_interrupt_notifier;
static std::array<int, 3> sig_interrupt_fds;